svelte
svelte copied to clipboard
Cannot use Tailwind's `@apply` on a selector within a media query
Describe the bug
It seems that you cannot use the Tailwind @apply
syntax to add styles to a selector that is nested within a media query. An example use-case would be applying a Tailwind background color to the body
tag for dark mode, which is currently a little challenging since <svelte:body>
does not accept a class
attribute.
For example, this code causes a build error
@media (prefers-color-scheme: dark) {
:global(body) {
@apply bg-gray-900;
}
}
While these are fine
@media (prefers-color-scheme: dark) {
:global(body) {
background: red;
}
}
:global(body) {
@apply bg-gray-900;
}
I believe that this is the same error, but that issue was closed by the opener without a resolution
https://github.com/sveltejs/svelte/issues/6638
Reproduction
https://github.com/alexlafroscia/__demo-tailwind-mq-apply-error
Logs
end must be greater than start
Error: end must be greater than start
at MagicString.remove (file:///Users/alexlafroscia/Code/github.com/alexlafroscia/demo-tailwind-mq-apply-error/node_modules/svelte/compiler.mjs:29632:27)
at file:///Users/alexlafroscia/Code/github.com/alexlafroscia/demo-tailwind-mq-apply-error/node_modules/svelte/compiler.mjs:30648:26
at Array.forEach (<anonymous>)
at Atrule$1.minify (file:///Users/alexlafroscia/Code/github.com/alexlafroscia/demo-tailwind-mq-apply-error/node_modules/svelte/compiler.mjs:30646:27)
at file:///Users/alexlafroscia/Code/github.com/alexlafroscia/demo-tailwind-mq-apply-error/node_modules/svelte/compiler.mjs:30801:23
at Array.forEach (<anonymous>)
at Stylesheet.render (file:///Users/alexlafroscia/Code/github.com/alexlafroscia/demo-tailwind-mq-apply-error/node_modules/svelte/compiler.mjs:30798:23)
at ssr (file:///Users/alexlafroscia/Code/github.com/alexlafroscia/demo-tailwind-mq-apply-error/node_modules/svelte/compiler.mjs:28574:30)
at compile (file:///Users/alexlafroscia/Code/github.com/alexlafroscia/demo-tailwind-mq-apply-error/node_modules/svelte/compiler.mjs:32273:15)
at compileSvelte2 (file:///Users/alexlafroscia/Code/github.com/alexlafroscia/demo-tailwind-mq-apply-error/node_modules/@sveltejs/vite-plugin-svelte/dist/index.js:320:20)
System Info
System:
OS: macOS 12.3.1
CPU: (10) arm64 Apple M1 Pro
Memory: 147.81 MB / 16.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 16.14.2 - ~/.volta/tools/image/node/16.14.2/bin/node
npm: 8.5.0 - ~/.volta/tools/image/node/16.14.2/bin/npm
Watchman: 2022.03.21.00 - /opt/homebrew/bin/watchman
Browsers:
Chrome: 101.0.4951.54
Safari: 15.4
npmPackages:
svelte: ^3.44.0 => 3.48.0
Severity
annoyance
From doing a little digging, I've noticed a few things:
- It doesn't seem like Tailwind itself is part of the problem. As an accident, I forgot to create a
postcss.config.cjs
file for my demo reproduction, so Tailwind isn't even running; Svelte (or SvelteKit; I'm not sure which) seems to just choke on the@apply
line within a media query - Nested media queries in general are not the issue; placing one
@media
within another@media
does not cause a problem. The@apply
syntax specifically within a media query is what seems to cause the error
From what I know, it's a bad practice to use the @apply
inside <style> ... </style>
.
See what they say in the Tailwind Docs: https://tailwindcss.com/docs/functions-and-directives#using-apply-with-per-component-css
under-the-hood, frameworks like Vue and Svelte are processing every single
I'm not sure if this applies tough (no pun intended), since you're using it inside __layout.svelte
with :global()
I would put the class directly on app.css
or, preferably, app.html
<!-- app.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%svelte.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%svelte.head%
</head>
<body class="dark:bg-gray-900">
<div>%svelte.body%</div>
</body>
</html>
Just leaving this here in case anyone stumbles on to this thread, hopefully it might save someone the time I wasted 🤪:
I had the same issue except that I was nesting @apply
inside of @screen
. But as @heloineto said, avoid using Tailwind funcs inside <style> ... </style>
. It sounds obvious, but my experience taught me that aside from the aforementioned reasons there is a very non-trivial performance implication as well. So if you're using Tailwind with Svelte, just to recap:
Don't
- Use Tailwind funcs inside
<style>
or risk Tailwind running over and over
Do
- Use
<style>
for handcrafted, component scoped CSS (if you need to) - Follow normal Tailwind conventions and only use the utilities inside the actual component markup (doesn't apply to OP), or ...
- If possible, try to abstract your classes to something more generic that you can implement in
tailwind.config.js
orapp.css
- If it really is very specific and not suited to a component (as in the case of @alexlafroscia), you may need to go the
app.css
route