svelte icon indicating copy to clipboard operation
svelte copied to clipboard

Tailwind @apply breaks with Svelte 5 (alpha 57)

Open svelte-kit-so-good opened this issue 1 year ago • 11 comments
trafficstars

Describe the bug

Video shows it best; starting with alpha 57 the tailwind @apply rule breaks (specifically with darkmode):

https://github.com/sveltejs/svelte/assets/153018600/4eaa759a-044e-4c34-811c-b5648374924d

Reproduction

SvelteLab

Logs

No response

System Info

Svelte v5.0.0-next.57 (breaks)
Svelte v5.0.0-next.56 (works)

Severity

annoyance

svelte-kit-so-good avatar Feb 18 '24 00:02 svelte-kit-so-good

@svelte-kit-so-good

  1. Update Tailwindcss to ^v3.4.1
  2. Modify the darkMode configuration in tailwind.config.mjs:
darkMode: ['variant', '&:where(:global(.dark), :global(.dark) *)']
  1. Configure darkMode for Astro + Svelte If you are using Astro + Svelte, you need to configure darkMode differently in your Tailwind config file:
darkMode: ['variant', ['&:where(.dark, .dark *)', '&:where(:global(.dark), :global(.dark) *)']]

I'm not sure if this is the best practice, but it works for the current changes.

mwc avatar Feb 25 '24 06:02 mwc

The generated CSS is this:


    main.svelte-11sclw {
          /* tailwind @apply with 'dark:' breaks in alpha 57 */
      --tw-bg-opacity:1;
      background-color:rgb(219 234 254 / var(--tw-bg-opacity));
    }
    /* (unused) :is(html.dark-mode main) {
          --tw-bg-opacity:1;
      background-color:rgb(30 58 138 / var(--tw-bg-opacity));
}*/
    button.svelte-11sclw {
          
      width:50px;
      aspect-ratio:1/1;
      border-radius:10px;
      background:black;
      /* regular css works */
    }
    html.dark-mode button.svelte-11sclw {
                filter:invert(1);
      }

The problem is that Tailwind generates CSS which contains selectors that look unused to Svelte. The solution is to add adjust the Tailwind config by adding :global like this:

/** @type {import('tailwindcss').Config} */
export default {
-  darkMode: ["class", "html.dark-mode"],
+  darkMode: ["class", ":global(html.dark-mode)"],
  content: ["./src/**/*.{html,js,svelte,ts}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

Question: Was this an existing config from a Svelte 4 project? If so, we may need to adjust the breaking changes section to note that Svelte now supports :is and :where properly and therefore also adds the CSS treeshaking to it.

dummdidumm avatar Mar 05 '24 14:03 dummdidumm

Question: Was this an existing config from a Svelte 4 project? If so, we may need to adjust the breaking changes section to note that Svelte now supports :is and :where properly and therefore also adds the CSS treeshaking to it.

Yes. A config that worked from Svelte 4 up to and including Svelte 5 Alpha 56.

Edit: Oh .. yea no this is a non-solution. So my issue was only with using the @apply rule for the tailwind 'dark:' selector inside the

<div class="dark:bg-blue-900"/> 
<!--  even with breaking changes in alpha 57, this still worked-->
<!--  Breaks with your tailwind config :global() suggestion -->

svelte-kit-so-good avatar Mar 05 '24 16:03 svelte-kit-so-good

Reopening and giving it the documentation level - we should note this in the breaking changes.

dummdidumm avatar Mar 05 '24 16:03 dummdidumm

The problem is that Tailwind generates CSS which contains selectors that look unused to Svelte. The solution is to add adjust the Tailwind config by adding :global like this:

/** @type {import('tailwindcss').Config} */
export default {
-  darkMode: ["class", "html.dark-mode"],
+  darkMode: ["class", ":global(html.dark-mode)"],
  content: ["./src/**/*.{html,js,svelte,ts}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

Unfortunately, this isn't a fix. While it does fix the cases where @apply is used, everywhere else breaks now. So the problem is now the inverse, where styles defined inline with the dark: modifier (e.g. class="dark:bg-blue-900") are now the broken case.

Edit: Here's a REPL that I find to be a just bit easier to play with and demonstrate.

AdrianGonz97 avatar Mar 05 '24 18:03 AdrianGonz97

With great pain comes great responsibility ...

TL;DR: Uno continues working; Tailwind breaks from Svelte 5 Alpha 57

I went ahead and made a Stackblitz for UnoCSS and Tailwind. In the

  • @apply rule with 'dark:' breaks with both Tailwind and Uno (using Tailwind plugin for Uno)
  • --at-apply rule of Uno with 'dark:' works!

svelte-kit-so-good avatar Mar 05 '24 23:03 svelte-kit-so-good

REPL, after modifying tailwind.config.cjs as shown below, your code doesn't work? @svelte-kit-so-good

/** @type {import('tailwindcss').Config}*/
const config = {
- darkMode: "class",
+ darkMode: ['variant', ['&:where(.dark, .dark *)', '&:where(:global(.dark), :global(.dark) *)']],

  content: ["./src/**/*.{html,js,svelte,ts}"],

  theme: {
    extend: {},
  },

  plugins: [],
};

module.exports = config;

mwc avatar Mar 06 '24 08:03 mwc

@mwc yes this is a solution, but I would venture to say it's not a satisfactory one since:

  1. it breaks the default behaviour with Tailwind, that just worked' up until alpha 57 — even before Svelte 5.
  2. As I showed with Uno stackblitz, the default behaviour continues to work

Personally with Tailwind I have just left things inline or have moved things to the style section like:

<style lang="postcss">
	.some-class {
		@apply some-utility-classes;
		:global(html.dark) & {
			@apply some-more utility-classes;
		}
	}
</style>

svelte-kit-so-good avatar Mar 06 '24 20:03 svelte-kit-so-good

It works with v119, can we close this?

frederikhors avatar Apr 30 '24 15:04 frederikhors

It works with v119, can we close this?

No? There's multiple demos to choose from here:

  • do npm i svelte@next in AdrianGonz97's SvelteLab demo, or
  • pnpm i svelte@next in my last Stackblitz Tailwind demo

svelte-kit-so-good avatar Apr 30 '24 15:04 svelte-kit-so-good

REPL, after modifying tailwind.config.cjs as shown below, your code doesn't work? @svelte-kit-so-good

/** @type {import('tailwindcss').Config}*/
const config = {
- darkMode: "class",
+ darkMode: ['variant', ['&:where(.dark, .dark *)', '&:where(:global(.dark), :global(.dark) *)']],

  content: ["./src/**/*.{html,js,svelte,ts}"],

  theme: {
    extend: {},
  },

  plugins: [],
};

module.exports = config;

This works, but for the dark:hover:bg- this doesn't work.

PS: It does, but slightly different.

bg-white hover:bg-neutral-50 dark:bg-neutral-800

Use to work, and when hovered, it used to not apply the hover effect for dark mode, but now

bg-white hover:bg-neutral-50 dark:bg-neutral-800 dark:hover:bg-neutral-800

dark:hover:bg-neutral-800 is required.

Bishwas-py avatar Jun 17 '24 03:06 Bishwas-py

REPL, after modifying tailwind.config.cjs as shown below, your code doesn't work? @svelte-kit-so-good

/** @type {import('tailwindcss').Config}*/
const config = {
- darkMode: "class",
+ darkMode: ['variant', ['&:where(.dark, .dark *)', '&:where(:global(.dark), :global(.dark) *)']],

  content: ["./src/**/*.{html,js,svelte,ts}"],

  theme: {
    extend: {},
  },

  plugins: [],
};

module.exports = config;

with this solution, I am getting Unused CSS selector ".dark *" everywhere.

Bishwas-py avatar Jul 21 '24 08:07 Bishwas-py