Earlier I linked to this project:
…and I still broadly like its approach to the problem but what started to nag at me is that I don’t think this problem should have existed in the first place.
Shadow DOM is unique among the technologies in the web components stack in that it breaks away from one of the conventions of the web that it inherited from the Unix Philosophy:
do one thing and do it well
Now, while the web and Unix’s descendants have been practically joined at the hip throughout their history, web standardisation has never been driven by the same principles and guidelines as those that have guided software development on Linux or *BSD.
But web development certainly has and that culture has informed web standards work.
Most web standards that reach broad use follow this principle. That ‘one thing’ is sometimes an extremely complicated thing, as with CSS Grid, but more often than not you tend to have features that start out narrow in scope and only get additional features later on.
The Shadow DOM breaks all of that. It does CSS scoping—prevents styles from escaping its scope; CSS encapsulation—styles from outside the scope can’t get in; event encapsulation; DOM encapsulation; and rudimentary template composition through <slot>
. And more.
That’s five features that, for most organisations, have distinct and often incompatible use cases.
The Shadow DOM was designed by a huge tech company and was mostly informed by the needs of exceptionally large organisations with thousands of engineers. Companies that size need extreme encapsulation because there is no way that they can safely collaborate on each and every component.
But, much like Java is useless for most organisations but loved by the enterprise, this encapsulation is just a huge pain in the ass for everybody else.
(A good heuristic for which kind of organisation yours is: irrespective of the language, would Ruby on Rails’s architecture and feature set suit your organisation’s needs? If so, then Shadow DOM is probably going to be a pain in the ass for you.)
To get a sense of the additional work this creates for people just look at the project I linked to above: it practically reimplements every single relevant CSS property as a custom variable.
We end up having to do this because,while non-gargantuan organisations have strong use cases for CSS encapsulation and scoping, those needs rarely coincide.
Most content website and form-oriented service sites (think government institutions) need CSS scoping so that the functional CSS for a component doesn’t bleed out and cause inconsistent styling.
But the core need there is consistent styling, which means that CSS encapsulation is a big problem. To make Shadow DOM components look visually consistent with the rest of the site we need to do a substantial amount of additional work which, a lot of the time, more than offsets the work savings represented by CSS scoping.
This is applies as well to Shadow DOM’s other features: the work saved by DOM encapsulation is lost again by having to redo or alter the scripts used to add accessible interactivity such as modals.
Shadow DOM can be useful for progressive enhancement and other problems but represents too much additional work to be used everywhere. More importantly, as a whole it represents a huge departure from how most of the rest of the web development stack behaves.
Having to use the Shadow DOM for web development is a bit like having to add islands of Java code in the middle of your Ruby script just for a single use case. Some developers would probably love being able to do so because they see Ruby as an unreliable, non-enterprise-y, liability.
But if you love Ruby, it would be a huge pain in the ass.
One of the reasons why developers are loving Svelte is that it offers many of the same features as the Shadow DOM, using the same overall design as the standard uses, but without bundling them into a ‘use one; use all’ package.
- You get style scoping, without encapsulation, by including a
<style>
element in the component itself. - You get
<slot>
-based template composition without buying into DOM encapsulation (unless you want to, in which case you can compile the component as a custom element that uses the Shadow DOM). - You get encapsulated component events without having to encapsulate DOM events, native or custom.
These are broadly the same features as the Shadow DOM brings to the table but they are much more useful because they can be used individually. You can mix and match global and scoped styles. You can use <slot>
with or without CSS scoping. You can encapsulate events or you can just use native DOM custom events that aren’t encapsulated.
I’m not saying that everybody should go out and use Svelte. I am saying that Svelte represents a failure in web standardisation. It takes the shape that the platform should have taken but didn’t.
Unfortunately, I’m not sure any of the browser vendors have the appetite or capability to fix the situation.
Which is how frameworks get so popular.