Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pushing Styles into Shadow DOM (@shadow rules) #1053

Open
DarkWiiPlayer opened this issue Mar 19, 2024 · 10 comments
Open

Pushing Styles into Shadow DOM (@shadow rules) #1053

DarkWiiPlayer opened this issue Mar 19, 2024 · 10 comments

Comments

@DarkWiiPlayer
Copy link

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.

@knowler
Copy link

knowler commented Mar 19, 2024

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.

@knowler
Copy link

knowler commented Mar 19, 2024

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.

@DarkWiiPlayer
Copy link
Author

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.

@knowler
Copy link

knowler commented Mar 19, 2024

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.

This is what I was thinking.

@justinfagnani
Copy link
Contributor

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.

@EisenbergEffect
Copy link
Contributor

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.

@DarkWiiPlayer
Copy link
Author

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.

@michaelwarren1106
Copy link

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.

@justinfagnani
Copy link
Contributor

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.

@DarkWiiPlayer
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants