svelte
svelte copied to clipboard
Tailwind @apply breaks with Svelte 5 (alpha 57)
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
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
- Update
Tailwindcssto ^v3.4.1 - Modify the
darkModeconfiguration intailwind.config.mjs:
darkMode: ['variant', '&:where(:global(.dark), :global(.dark) *)']
- Configure
darkModefor Astro + Svelte If you are usingAstro+Svelte, you need to configuredarkModedifferently 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.
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.
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
:isand:whereproperly 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 -->
Reopening and giving it the documentation level - we should note this in the breaking changes.
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
:globallike 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.
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
@applyrule with 'dark:' breaks with both Tailwind and Uno (using Tailwind plugin for Uno)--at-apply ruleof Uno with 'dark:' works!
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 yes this is a solution, but I would venture to say it's not a satisfactory one since:
- it breaks the default behaviour with Tailwind, that just worked' up until alpha 57 — even before Svelte 5.
- 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>
It works with v119, can we close this?
It works with v119, can we close this?
No? There's multiple demos to choose from here:
- do
npm i svelte@nextin AdrianGonz97's SvelteLab demo, or pnpm i svelte@nextin my last Stackblitz Tailwind demo
REPL, after modifying
tailwind.config.cjsas 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-800Use 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-800is required.
REPL, after modifying
tailwind.config.cjsas 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.