Pushing Styles into Shadow DOM (`@shadow` rules)
DarkWiiPlayer opened this issue · comments
In the discussion around #909, one requirement that has been brought up repeatedly is for a mechanism whereby the website can define Styles that would apply inside a web component's shadow DOM.
Generally speaking, the requirement comes down to something like this:
As a user of web components, I want to override styles inside the shadow DOM beyond what it allows for with
:part()
s. I do not want to or cannot modify the internal state of the custom element nor its source code to achieve this.
As a starting point for discussion, I'd like to propose something like this:
/* Document-level style-sheet */
@shadow (my-element) {
p { color: red; }
}
It seems reasonable to restrict this only to mode="open"
shadow DOMs, and that this should be applied to nested shadow DOMs out of the box. The selector for the actual element could be a complete selector including combinators, or could be restricted to element names with at least one -
In the discussion around #909 several other mechanisms have been proposed to achieve this.
@knowler suggested using a :shadowroot
pseudo-class inside @scope
rules to scope styles to the root of the shadow DOM, effectively pushing these styles into the shadow DOM in the process.
@jaredcwhite proposed using :shadowdom
inside a @scope
block to select elements inside the shadow-dom attached to the scope's root node.
There's probably more that I'm missing.
The selector for the actual element could be a complete selector including combinators, or could be restricted to element names with at least one -
I think it would be most useful to be the former: it should at least allow a compound selector. Especially since non-custom elements can have shadow roots too.
I like this idea, but I do think that something using @scope
would have greater potential since then you could use the styles in different contexts (i.e. in the document and in shadow roots). I think being able to do that is an important success criterion for the whole external styling of shadow roots initiative.
then you could use the styles in different contexts (i.e. in the document and in shadow roots)
Could this be done using a "magic" selector, like, say @shadow (:root, my-document)
to include the light-dom? Or are there other cases where this wouldn't work but @scope
would?
I personally like the idea of using @scope
, but I'm worried that it might be a nightmare to figure out the specifics of how that would use, specially if the shadow-root isn't part of the scope selector (so if it appears inside the scope using some special selector)
Maybe something like @scope (:root, my-component::shadowroot)
and define ::shadowroot
to only work inside @scope
selectors (for now) would be a good compromise, where the potential for weird cases is smaller but there's still more flexibility than a new @
-Rule.
I do not want to or cannot modify the internal state of the custom element nor its source code to achieve this.
This is a case that I strongly believe we should not support.
Allowing page authors to override private state of components would be akin to asking TC39 to allow outside code to read private fields of classes or internal state of closures. It violates the contract set up by the library author and leads to fragile coupling that can put a undue burden on them.
It's fine for a component author to choose to relax encapsulation. It's not fine for someone else to easily break it.
Strongly agree with @justinfagnani on this point. There are situations where owners of design systems and components want to strongly enforce that certain things cannot be changed, and sometimes this has legal implications.
Allowing page authors to override private state of components would be akin to asking TC39 to allow outside code to read private fields of classes or internal state of closures. It violates the contract set up by the library author and leads to fragile coupling that can put a undue burden on them.
Correct me if I'm wrong, but in this regard, nothing would change here. Elements with an open shadow-DOM can already have their internal state messed with by the outside world and mode="closed"
exists precisely to give component authors a tool to make this impossible.
Allowing users who can already, technically speaking, insert entire style sheets into a shadow-DOM from the outside, or even make more significant changes to its internal structure, wouldn't really change anything in that regard.
i also agree with justin and rob. we should let existing encapsulated components stay that way.
another point about this is that in a future world where open stylable components exist, there will be much less of a need to force push styles to an encapsulated component, because the ability to relax encapsulation will also exist. if open stylable components come first, imo there will be almost no need for pushing styles into a non-open-stylable component because devs can just make open stylable components in the first place, or choose to only use third party components if they are open-stylable.
Correct me if I'm wrong, but in this regard, nothing would change here. Elements with an open shadow-DOM can already have their internal state messed with by the outside world and mode="closed" exists precisely to give component authors a tool to make this impossible.
This isn't correct because currently CSS cannot select into open shadow roots. Allowing that is breaking the contract currently provided to shadow roots. This is exactly why I proposed #909, because it is a change to allow CSS to select into shadow roots and the web component author, not the page author, should opt into that.
Correct me if I'm wrong, but in this regard, nothing would change here. Elements with an open shadow-DOM can already have their internal state messed with by the outside world and mode="closed" exists precisely to give component authors a tool to make this impossible.
This isn't correct because currently CSS cannot select into open shadow roots. Allowing that is breaking the contract currently provided to shadow roots. This is exactly why I proposed #909, because it is a change to allow CSS to select into shadow roots and the web component author, not the page author, should opt into that.
I'm not quite seeing how this is worse than allowing the outside to reach into the shadow DOM and just insert a style tag there; or worse yet, delete random nodes.