webc
webc copied to clipboard
CSS: Support scoping inner elements of a webc file
Assumption about the current state:
If I have the file:
<div>
<h1>Example</h1>
<p>Content</p>
</div>
<style webc:scoped>
:host h1 {
color: aliceblue;
}
:host p {
color: blanchedalmond;
}
</style>
After compilation I would currently see:
{
html: "<div class=\"wcl2xedjk\"><h1>Example</h1><p>Content</p></div>",
css: [".wcl2xedjk h1{color:aliceblue}.wcl2xedjk p{color:blanchedalmond}"],
}
Main concern:
For components that wrap another component, this isn't scoped enough to prevent style leakage. For example if our component above had a child component within it, and that child component also contained an h1
element, then .wcl2xedjk h1
would apply and turn it aliceblue
.
Desired behaviour:
In Svelte's CSS scoping, I can write the following:
<div>
<h1>Example</h1>
<p>Content</p>
</div>
<style>
h1 {
color: aliceblue;
}
p {
color: blanchedalmond;
}
</style>
Which would provide me something along the psuedo-lines of
{
html: "<div><h1 class=\"kziuyb\">Example</h1><p class=\"wgrhia\">Content</p></div>",
css: ["h1.kziuyb{color:aliceblue}p.wgrhia{color:blanchedalmond}"],
}
Where the styles are scoped directly to the elements they applied to.
Implementation:
In (my) ideal world this would happen automatically when webc:scoped
is applied. Alternatively to keep it opt-in it one could utilize something like a :host
pseudo-class wrapping styles:
<style webc:scoped>
:host(h1) {
color: aliceblue;
}
:host(p) {
color: blanchedalmond;
}
</style>
Ideally slightly more complex selectors would also be handled, so h1 + p:first-child
could become h1.qwerty + p.asdfgh:first-child
Reclassifying this one as a bug
I’m waffling back and forth here because I do kinda think this is okay and as a better short term solution I’d like to ship an example of how to override the webc:scoped
behavior with any arbitrary css scoping library e.g. css modules maybe? Any opinions on what a good next-level library for this might be?
Makes sense. I don't know of any css scoping libraries myself, but that would be a cool thing to find
lightningcss
might be a good library to show how to use css modules with. If not, postcss-modules
is another option (i believe this is what vue uses under-the-hood as well). both of these solve the inner-element scoping problem and they give you a json mapping of the original vs transformed class name, which could be substituted against webc's own internal mapping.
also worth mentioning that native scoping is coming and it might be good to start thinking about it. for example, webc could manage a unique hash to pass inside @scope
.
This is still important as long as scoped prefixing occurs before transforming... currently, the CSS being fed to a preprocessor is not what the developer wrote, but the result of applying the prefix transform. This creates unintended side effects.