HTML elements can style themselves now using the @scope rule. (It's Baseline Newly Available.) Unlike the "style" attribute, @scope blocks can include @media and other @ rules. You can't get more self-contained than this.
<swim-lane>
<style>
@scope {
background: pink;
b {
background: lightblue
}
@media (max-width: 650px) {
/* Mobile responsive styles */
}
}
</style>
something <b>cool</b>
</swim-lane>
You can also extract them to a CSS file, instead. @scope (swim-lane) { /* ... */ }
The reason approaches like this continue to draw crowds is that Web Components™ as a term is a confluence of the Custom Elements JS API and Shadow DOM.Shadow DOM is awful. Nobody should be using it for anything, ever. (It's required for putting child-element "slots" in custom elements, and so nobody should use those, either.) Shadow DOM is like an iframe in your page; styles can't escape the shadow root and they can't get into the shadow root, either. IDs are scoped in shadow roots, too, so the aria-labelledby attribute can't get in or out, either.
@scope is the right abstraction: parent styles can cascade in, but the component's styles won't escape the element, giving you all of the (limited) performance advantages of Shadow DOM with none of the drawbacks.
That's styling itself sure, but it's not self-evidently self-contained. Does every component emit those styles? Are they in the page stylesheet? How do they get loaded?
Counterpoint: Shadow DOM is great. People should be using it more. It's the only DOM primitive that allows for interoperable composition. Without it you're at the mercy of frameworks for being able to compose container components out of internal structure and external children.
Decoupling slots from shadow dom would make custom elements even better.
I love custom elements. For non React.js apps I use them to create islands of reactivity. With Vue each custom element becomes a mini app, and can be easily lazy loaded for example. Due to how Vue 3 works, it’s even easy to share state & routing between them when required.
They should really move the most worthwhile features of shadow dom into custom elements: slots and the template shadow-roots, and associated forms are actually nice.
It’s all the extra stuff, like styling issues, that make it a pain in the behind