Open techmunk opened 5 months ago
Attempting to approach this in svelte 5 with svelte-kit 2 and the proposed alternative preprocessing doesn't seem to work as expected. If the preprocessor only declares the css layer component styles should target, it appears to supersede the root css's declared layer order. In the case of tailwind v4, this means the base
(preflight) layer ends up applying resets over component styles.
/**
* @param {string} layerName
* @see https://github.com/sveltejs/svelte/issues/11345
*/
function csslayer(layerName) {
return {
name: 'svelte-css-layer',
style: ({ content }) => {
return {
code: `@layer ${layerName} { ${content} }`,
};
},
};
}
/**
* @type {import('@sveltejs/kit').Config}
*/
const config = {
extensions: ['.svelte'],
preprocess: [csslayer('components')],
kit: {
adapter: adapter(),
},
};
export default config;
/* app.css */
@layer base, components, utilities;
@import 'tailwindcss/preflight' layer(base);
@import 'tailwindcss/utilities' layer(utilities);
@theme {...}
<!-- +layout.svelte -->
<script lang="ts">
import '../app.css';
let { children } = $props();
</script>
{@render children()}
results in this layer ordering when inspecting the DOM:
3: implicit outer layer
0: components
1: base
2: utilities
but re-specifying the order in the preprocessor works
{ //...
style: ({ content }) => {
return {
code: `@layer base; @layer ${layerName} { ${content} }`,
};
}
}
3: implicit outer layer
0: base
1: components
2: utilities
@iolyd it does appear that the component CSS is injected into the DOM prior to the app.css loaded by +layout.svelte
, so the svelte
layer ends up getting created first, and therefore has the lowest precedence.
Adding (from my example)
<style type="text/css">
@layer base, theme, svelte, components, utilities;
</style>
in app.html
above %sveltekit.head% seems to also resolve this.
I have not tried this in a preview build, but this is how the dev server seems to work.
For my previous comment, this behaviour is described in the MDN docs in the last paragraph of this section https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers#the_layer_statement_at-rule_for_named_layers
Adding paragraph from MDN for context.
@layer theme, layout, utilities;
If the above statement is the first line of a site's CSS, the layer order will be theme, layout, and utilities. If some layers were created prior to the above statement, as long as layers with these names don't already exist, these three layers will be created and added to the end of the list of existing layers. However, if a layer with the same name already exists, then the above statement will create only two new layers. For example, if layout already existed, only theme and utilities will be created, but the order of layers, in this case, will be layout, theme, and utilities.
@techmunk, yes I am aware of the CSS spec, though without any particular reason I expected global stylesheets imported in script tags to be processed and inserted to the DOM before component styles.
Describe the problem
The tailwind v4 alpha uses native cascade layers
@layer
which can be read about on the MDN docs.The component CSS that is rendered by sveltkit always puts CSS in the anonymous layer, which always takes precedence.
For example, a third party svelte component that looks like this:
And used like this
With styles.css being
Will result in the background always being blue due to how CSS layers work with all the tailwind utility classes being the in the
@utilities
, layer. I feel this is somewhat unexpected to a developer using a component with tailwind, especailly given the component author has tried to remove the problem by using the:where
pseudo class.Describe the proposed solution
I'm wondering if an option should be added to the sveltekit config to allow component CSS to be wrapped in a layer so it can be handled better with native CSS layers.
I've had success using this preprocess function (in Svelte 5)
My
svelte.config.js
file then looks like this.And my
styles.css
changes to:I have a codesandbox here that puts it all together.
Alternatives considered
No response
Importance
nice to have
Additional Information
I think as tailwind v4 adoption grows, this is likely to become a larger issue. I'm not sure if this should target sveltekit, or svelte itself but I felt this interesting enough to raise an issue about.