-
Notifications
You must be signed in to change notification settings - Fork 52
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
Consider using Shadow Parts as an alternative to pseudo-elements for structure and user styling #190
Comments
Can you give a bit more detail on this? As in, why would changing the pseudo-tree be bad, but changing the shadow-tree be fine? The benefit of the shadow tree is developers could add their own elements for the transition, and use familiar APIs like |
Yeah. Even if the tree structure isn't directly expressed in the selector the CSS to customize the transition set by developers will assume a particular tree structure. It's part of the API contract either way.
I'm hoping that we can add the subset of the Element API, that makes sense to expose, via CSSPseudoElement as we learn developer use-cases. |
I was thinking in the sense that CSS would be hardcoding the nesting for pseudo-elements, such that if a UA was to change some internal representation (like wrapping everything in another container, adding a new element, etc) it would be observable. As @khushalsagar points out, maybe it's optimistic to think this could happen in either case since authors will write CSS based on the structure. Regardless, it may be subjective but I find the Shadow Parts syntax more ergonomic, and that the shadow DOM more intuitively expresses what the feature is doing to a web developer.
@emilio do you have thoughts on this? I was actually imagining that the UA DOM wouldn't be exposed to scripting to avoid the challenge here, but if access to DOM APIs is a requirement then I actually don't know if it's better to add a subset of those APIs to pseudo-elements, or restrict a subset of the APIs from UA shadow content. You probably have more context and an opinion here. |
Hmmm, the API feels similar to me for both once we have the descendent selector for pseudo-elements but curious to hear thoughts from other folks too. @tabatkins for CSS stuff. Pseudo-elements root:: :>> outgoing-image(root) {
...
} document.documentElement.animate(
{
...
},
{
// Specify which pseudo-element to animate
pseudoElement: ":: :>> outgoing-image(root)",
}
); Shadow DOM root::part(page-transition-root-outgoing-image) {
...
} document.documentElement.animate(
{
...
},
{
// Specify which pseudo-element to animate
pseudoElement: "::part(page-transition-root-outgoing-image)",
}
); I'll also look into any other issues with attaching a shadow DOM to the root element. I'll admit that while implementing this I only tried the shadow DOM under pseudo-element (which ran into issues with multiple feature doing flat tree traversal) and a tree of pseudo-elements.
The WA-API is definitely a requirement but that can be exposed via the part selector for the shadow DOM case too. @jakearchibald built a bunch of interesting demos which benefited from access to APIs like getBoundingClientRect and inline style. But each case we discussed has been a capability we could see being exposed for all pseudo-elements and one of the reasons they seemed like the right conceptual fit. |
Note in particular that the nested structure isn't just for convenience, but is in fact required in order to get blending between before/after states working correctly. So the structure is even depended on by the current spec! More generally, I'm against this change. The pseudos aren't, actually, "on" any element at all; we attach them to the root just because syntactically they need to be on something, but in layout they're moved into the top layer and thus paint completely independently anyway. On the other hand, putting a UA shadow root on an element is meaningful and observable; it can't co-exist with an author shadow root. Putting a shadow root on |
My understanding is that it's not possible to attach a shadow root on the html element from https://dom.spec.whatwg.org/#dom-element-attachshadow:
Regardless, I think there have been some really good points raised so far here and it helps me better understand the decision to use pseudo-elements. I'd like to see if Emilio or others have thoughts but I don't feel strongly enough to keep this open myself. |
Yeah, author shadow dom on And exposing them via shadow parts doesn't mean that they are exposed to script, so I'm not sure what that is about, they wouldn't be exposed to script just like the current pseudos aren't. In general I don't know there'd be any particular behavior difference here other than in the case where the document element is not an |
Ah, I'd forgotten that there was a specific restriction against
The point was about exposing the existence of UA-defined shadow parts, not about exposing the objects via script. The former hasn't been done yet.
Conversely, we haven't exposed any UA-defined parts at all in the platform yet, whereas pseudo-elements are common. And, while nested pseudo structures haven't been defined in a spec yet, they definitely exist in browser-specific forms, like the scrollbar pseudos. So I think there's just as strong, if not stronger, of an argument for pseudos being the existing platform feature we're relying on. ^_^ More generally, @emilio, do have specific reasons to not expose these as pseudo-elements? Does this add some difficulties that I'm not aware of? |
Not difficulties per se, but a bunch of special-case code around the style engine. This is true of ~every engine afaict. Pseudo-elements generally need special code, in parsing/serialization/matching, and pseudo-element generation, see all the usages of the page transitions pseudos in Chromium for example. Introducing a bunch of new pseudos and more complex tree structures for a feature that is already complex enough on its own seems pretty overkill to me, but I dunno, might not be the hill to die on. It just feels really over-complicated when the platform already provides a way of doing that that we could use for this rather special case... |
@emilio the API currently exposed for these pseudo-elements is the CSS selector and the few script APIs which are already exposed for pseudo-elements. Without the descendant pseudo-element selector (yet to be spec'd and implemented), that would look something like the following: html::page-transition::container(foo) {
...
} document.documentElement.animate(..., { pseudoElement: "::page-transition::container(foo)" }); Do you think an API surface like this could allow both a shadow DOM and pseudo-element implementation? We need to have a selector syntax to target these elements irrespective of the backing implementation. The shadow DOM version implies that this syntax could be the part selector. But if the additional parsing code needed for this chaining syntax is reasonable to support with a shadow DOM too then we can go with pseudo-elements for now. This will help in deferring a decision on the exact backing implementation before committing to additional APIs which are tightly coupled to either of the 2. Since one of your concerns with the pseudo-element approach is the special code in parsing/matching, I wasn't sure if this idea helps. |
No, ::part() is unfortunately not equivalent to nested pseudos, as it very specifically and purposely does not expose nesting details. So in particular, the use-case for detecting whether a transition has an incoming and/or outgoing image won't work without additional effort twiddling part names to reveal that info. |
Sorry if my comment was confusing, I wasn't advocating for using ::part(). But the idea of exposing the pseudo-element based CSS syntax which an engine could choose to back with shadow DOM or pseudo-elements. There are use-cases where we've added bespoke pseudo-element selectors for elements in UA shadow DOM (like ::placeholder). But the fact that we have nested pseudo-elements here makes it likely that pseudo-elements end up being the easier backing implementation. You brought up another good point that there are use-cases where developers want to conditionally apply CSS based on the tree structure, that was brought up here. This can work with the nested pseudo-element syntax combined with has but I don't see it working with part. So if we have use-cases like this which need a pseudo-element based syntax, is it simpler to back it with shadow DOM vs pseudo-elements? |
I'd like to consider Shadow Parts as an alternative to using nested pseudo-element structure for user styling. Maybe this has already been discussed and dismissed, but I wanted to raise this coming out of mozilla/standards-positions#677.
I'm not sure it's ideal to expose the deep pseudo-element tree to developers - both ergonimcally, and in the case where a UA may want to change the internal representation of the various parts i.e. if future iterations introduce new features which would benefit from a change in the tree.
So instead of having something like
with
Could there be something like:
with
Some of the potential challenges with this approach (at least the ones I've thought of) are:
The text was updated successfully, but these errors were encountered: