sheetify
sheetify copied to clipboard
Styles bleed through
Example:
/* comment.css */
:host .header {
color: blue;
}
/* article.css */
:host .header {
color: red;
}
<article class="_article-hash">
<h1 class="header">Article title</h1>
<section class="comments">
<article class="_comment-hash">
<h2 class="header">Comment title</h2>
</article>
<section>
</article>
Comment header will be either red or blue, depending on the order of file inclusion. You can guard with > selectors, but this makes your CSS dependent on the exact DOM structure.
Shadow DOM naturally does not suffer from this.
BEM does not suffer from this, due to using unique names.
CSS Modules does not suffer from this, due to rewriting all class names.
Vue implementation of scoped styles does not suffer from this, due to rewriting HTML too and using different prefixing technique (<div class="header" _article-hash> and .header[_article-hash]).
Oops, yeah - good point, thanks for finding this and reporting it. Bit swamped with work right now, so don't quite have time to fix this. What do you propose the solution is to this?
The simplest solution I can think of is following the Vue approach with a slight change:
:host -> ._hash
.compound > .selector => .compound._hash > .selector._hash.
<article class="${articleHash}">
<h1 class="${articleHash} header">Article title</h1>
<section class="${articleHash} comments">
<article class="${commentHash}">
<h2 class="${commentHash} header">Comment title</h2>
</article>
<section>
</article>
This way whenever you reference a "local" class, you need to add the hash. But to do this manually is still cumbersome and error-prone.
Another solution is following the CSS Modules approach and rewriting classes:
:host -> ._host-hash
.compound > .selector => ._compound-hash > ._selector-hash.
<article class="${article.$host}">
<h1 class="${article.header}">Article title</h1>
<section class="${article.comments}">
<article class="${comment.$host}">
<h2 class="${comment.header}">Comment title</h2>
</article>
<section>
</article>
With this approach the library needs to worry about case, because JavaScript does not support the - in the names of variables. So the library either:
- Needs to promote using
camelCaseclasses, like CSS Modules does (otherwise developer would have to write something likeclass="${comment['snake-case']}", which is far from being nice), - Needs to promote
snake-caseand convert tocamelCaseinternally.