Closed khushalsagar closed 2 years ago
Another option uses part which relies on using a shadow DOM rooted at the html element. We were concerned that this would disallow developers from attaching their shadow DOM to the root but the spec already disallows that.
The structure for the shadow DOM would be the same as with pseudo-elements above. It has part attributes to match selectors. So for the example above:
<div part="page-transition">
<div part="container container-foo">
<div part="wrapper wrapper-foo">
<div part="incoming incoming-foo"></div>
<div part="outgoing outgoing-foo"></div>
</div>
</div>
</div>
And then selectors to target them can be:
/* Matches all container elements. */
html::part(container) {
...
}
/* Matches container element for foo. */
html::part(container-foo) {
...
}
The comment here brought up a use-case to conditionally apply CSS based on whether one of the pseudo-element exists, for example we only have the incoming image, using has. This syntax would rely on adding additional part names for this. For example:
<div part="page-transition">
<div part="container container-foo">
<div part="wrapper wrapper-foo">
<div part="incoming incoming-foo incoming-only-foo"></div>
</div>
</div>
</div>
Can use the following selector:
html::part(incoming-only-foo) {
...
}
The exact part names still up for bike-shedding.
Note that you can supply multiple part names in ::part()
, and it selects only parts that match all of them (like they were multiple class names in a compound selector). So we don't need to mix the element tags into the part names, we can just use them as part names directly, and they'd be selected like ::part(container foo)
.
I have some questions about shadow DOM and this API:
Special replaced elements: Currently in the pseudo element model, we have replaced elements that are specced to reflect either a captured snapshot or "live" dom, depending on the situation and that's just "magic" in the sense that particular pseudo element names are defined to be these elements. We're fairly safe in making these definitions because the developer has no way to also create these elements, they are limited to UA control. If we switch to shadow DOM, what elements would we use? I can see that the example above uses div
s with some part attributes, but presumably that would mean that the developer can also create these div
s with these attributes in the light dom or in their own shadow doms. Is there any way to preclude that? In other words, is it possible to have some "magic" element that the UA can add but that the developers can't, when it comes to shadow DOM? Just having a new element also seems insufficient since nothing is preventing the developers from creating new elements either
Element references: if we use shadow DOM, we also want to make sure that the developer can't reparent these elements or in general get a reference to them, other than selecting them for style via CSS selectors. I assume there is precedence for that, but I just wanted to make sure that this is already an established practice.
Scoped transitions: lastly, and this is outside of the scope of the current spec, but one future improvement that we've talked about for this API is scoping the transition to a subtree. Basically, since only one transition is allowed and that transition occupies the whole document, it makes it awkward to use in something like reusable components. For that, we'd like to work towards scoping the pseudo/shadow dom structure to be attached to an element other than html via some properties/js api calls and limit the transition to a subtree. Now, there are other technical challenges here, but if we switch to shadow dom it also adds another one: we wouldn't be able to attach this shadow dom to a custom element which already has a developer shadow dom attached. We would require something along the lines of a wrapper div right inside the shadow dom to act as a "root" for the purposes of this API. That seems like an ergonomics challenge for developers. I wonder if there are any elegant solutions here
1. is it possible to have some "magic" element that the UA can add but that the developers can't
I think we can explain this via the cascade. The image stuff only works when it's in this particular shadow DOM.
2. we also want to make sure that the developer can't reparent these elements or in general get a reference to them
That seems bad. One of the advantages of using shadow DOM would be allowing developers to get regular element references. Without this, we'll still have to go down the path of creating pseudo-element references, and it's not even clear if that should work for ::part
.
3. Scoped transitions: lastly, and this is outside of the scope of the current spec, but one future improvement that we've talked about for this API is scoping the transition to a subtree. Basically, since only one transition is allowed and that transition occupies the whole document, it makes it awkward to use in something like reusable components. For that, we'd like to work towards scoping the pseudo/shadow dom structure to be attached to an element other than html via some properties/js api calls and limit the transition to a subtree. Now, there are other technical challenges here, but if we switch to shadow dom it also adds another one: we wouldn't be able to attach this shadow dom to a custom element which already has a developer shadow dom attached.
Yeah, this is a huge issue. But similarly, it also seems weird that SET gets to claim the shadow DOM of the root element. Like, do we just get to own that space since we arrived first?
This is why, when I was thinking about doing this via shadow DOM, I suggested that the shadow root be attached to a pseudo-element. That's new and weird though.
Without this, we'll still have to go down the path of creating pseudo-element references, and it's not even clear if that should work for ::part
Did you mean references for script? The CSS API can be the same in both approaches with the use of ::part.
For script access, we don't want to allow script to do everything that the Element API allows (like reparenting the element out of the shadow DOM). So the choices for adding that later would be:
I did want WA-API to be available to script in the initial version of this feature. And it looks like you can't target an element in a shadow DOM using the ::part selector with pseudoElement option, as opposed to selectors which target pseudo-elements. This example doesn't work in Chrome/Firefox/Safari.
The Scoped transitions aspect is what makes shadow DOM dealbreaker for me. The fact that developers lose the ability to use an element, which is a shadow host, as the root for a scoped transition. We'd be forcing developers to add nodes just so the browser has an element to attach the transition's shadow DOM to.
Pseudo-elements and shadow DOM could be made equivalent in functionality given that both can be targeted in CSS the same way. But the desire for exploring shadow DOM (from the discussion here) is to have a potentially simpler implementation. Shadow DOM seems to push complexity from the implementor to developer.
do we just get to own that space since we arrived first?
You don't miss what you didn't have? ^_^
I suggested that the shadow root be attached to a pseudo-element
This is a road I don't want to go down. It gets really weird if a pseudo-element becomes an ancestor for real elements.
Did you mean references for script?
Yeah, sorry, I wasn't clear.
For script access, we don't want to allow script to do everything that the Element API allows (like reparenting the element out of the shadow DOM).
I think we could allow this. I'm assuming we could use the cascade to say the outgoing and incoming image elements don't 'work' outside of the shadow DOM.
I did want WA-API to be available to script in the initial version of this feature. And it looks like you can't target an element in a shadow DOM using the ::part selector with pseudoElement option
Oof, yeah, that's bad. It's an important part of the feature. I wonder if there's a good reason it doesn't work, and if it'd also cause issues with a CSSPseudoElement
reference.
The Scoped transitions aspect is what makes shadow DOM dealbreaker for me.
+1
I suggested that the shadow root be attached to a pseudo-element
This is a road I don't want to go down. It gets really weird if a pseudo-element becomes an ancestor for real elements.
Yeah, I imagine there are a lot of reasons why it's a bad idea.
is it possible to have some "magic" element that the UA can add but that the developers can't
I think we can explain this via the cascade. The image stuff only works when it's in this particular shadow DOM.
Yeah, magic is the way to go. They have to be in the proper tree and the proper structure, and we can determine that via magic (UA-only inherited CSS properties, for example, which is set on the elements via UA stylesheet and checked via internal code).
And it looks like you can't target an element in a shadow DOM using the ::part selector with pseudoElement option, as opposed to selectors which target pseudo-elements. This example doesn't work in Chrome/Firefox/Safari.
This is probably just a browser bug? The spec mentions ::part() when discussing target elements.
The CSS Working Group just discussed Pseudo-element Selectors for shared element transitions
.
I'm closing this issue in favour of resolving as 2 separate issues based on the TPAC discussion: #7928 and #7788.
We need to define the selector name and whether it takes an argument for each of the pseudo-elements that SET generates. For each tag on a DOM element via page-transition-tag (assuming its in both pages), the following tree is generated:
And all page-transition-container elements have the same ancestor, page-transition. If you write the full syntax, it would be something like this:
Which is a lot to type. #7346 will help with that but we want to avoid a dependency on that and make the chaining syntax easier to type. So one option is a shorter name and no arguments for everything except container, which would be something like:
The names
container
,wrapper
,incoming
andoutgoing
might seem too generic but they'll only show up under page-transition so could be fine?A caveat here is that once the descendant selector ships, you'll always need to reference the container to get to the images corresponding to a tag. Something like:
If everything under container does keep the argument then the above could be this instead:
But then the non-descendant selector would be:
I'm not sure which is better. @tabatkins @vmpstr.