w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.44k stars 657 forks source link

[web-animations-2] Enable using Web Animations API with nested pseudo elements #7469

Open khushalsagar opened 2 years ago

khushalsagar commented 2 years ago

The WA-API allows targeting pseudo elements originating from a DOM element using pseudoElement in KeyframeEffectOptions. See the following description in the spec here:

"pseudoElement, of type CSSOMString, nullable, defaulting to null The pseudo-element selector (which must be valid or null) used to specify the effect target given the target element."

This is currently limited to pseudo elements which are direct descendants of the target element. The proposal is to allow using any pseudo element selector to target nested pseudo elements originating from the target element. For example,

The following could be use to target a marker nested inside the before pseudo element.

element.animate(keyframes, {
      ...animationOptions,
      pseudoElement: "::before::marker",
});

Or with the new selectors introduced in #7346, the above could be this instead.

element.animate(keyframes, {
      ...animationOptions,
      pseudoElement: "::>>marker",
});

Since the selector above could match multiple elements, the effect target would resolve to the first element matching the selector (similar to 'document.querySelector').

The above use-case will be common with shared element transitions which generates a tree of pseudo elements to animate.

birtles commented 2 years ago

We probably need to ensure the selector matches a single pseudo-element since that's the current model: 1 animation per (pseudo-)element so I'm not sure about the latter syntax but the former seems fine. I think this can be added in Web Animations level 2.

khushalsagar commented 2 years ago

The motivation for the latter syntax is similar to the motivation for #7346. It can be quite cumbersome to write the full pseudo element hierarchy in the selector, especially with the trees being created for #6464.

If a pattern to select the first matching pseudo element seems like a footgun, we could also require that the selector should match a single element and consider it invalid if it matches more than 1. @jakearchibald any concerns with this idea?

heycam commented 2 years ago

Related, do we need to make any changes so that getComputedStyle(..., "::before::marker") works too?

khushalsagar commented 2 years ago

Yes, getComputedStyle would need a similar change. Thanks for pointing that out.

jakearchibald commented 2 years ago

If a pattern to select the first matching pseudo element seems like a footgun, we could also require that the selector should match a single element and consider it invalid if it matches more than 1. @jakearchibald any concerns with this idea?

I think we can say it acts like querySelector, where it matches the first element even if there are many matches.

Loirooriol commented 2 years ago

This is basically #4487

css-meeting-bot commented 2 years ago

The CSS Working Group just discussed [web-animations-2] Enable using Web Animations API with nested pseudo elements, and agreed to the following:

The full IRC log of that discussion <emilio> topic: [web-animations-2] Enable using Web Animations API with nested pseudo elements
<emilio> github: https://github.com/w3c/csswg-drafts/issues/7469
<vmpstr> khush_:
<emilio> khush_: this is about supporting nested pseudos in web-animations API
<emilio> ... there's an option to pass a string that right now is limited to direct descendants of the element
<emilio> ... so you can do `::before` but not `::before::marker`
<emilio> ... proposal is allowing any kind of syntax
<emilio> ... to allow you to select nested pseudos
<emilio> ... you could also use the descendant selector
<emilio> ... which is a nicer syntax to select a pseudo-tree
<emilio> ... there's the question of what to do when it matches multiple selectors
<flackr> q+
<emilio> ... so there's the option to make it invalid, or select the first like querySelector
<emilio> ack flackr
<emilio> flackr: if you can match multiple pseudos, does that mean that we're introducing a case where the pseudo-element can change over time?
<emilio> ... dunno if there are cases like this
<emilio> khush_: I'd say to select the pseudo-element when you make the animate() call
<emilio> ... and animation would terminate, just like you can remove `::before` styles mid-animation and the animation stops
<emilio> flackr: I suspect we should do this in the next lifecycle update so that there's no forced style resolution on `animate()`
<emilio> khush_: that's pre-existing I think, we already do that
<emilio> flackr: also current behavior is that animations keep running when the element disappears, and if it comes back it restarts
<emilio> khush_: not sure
<emilio> flackr: It'd be good to match the existing behavior for single pseudos
<emilio> ... not sure if this complicates matters a bit but there are existing patterns to follow
<Rossen_> q?
<emilio> Rossen_: So for the multiple pseudo case do you think we should stick to querySelector() or...?
<emilio> khush_: I'd say we should do that
<vmpstr> emilio: when you say any selector, what do you mean? you can't put any selector. Is there a syntax to define what exactly will be allowed?
<Rossen_> emilio: when you say "any selector" what do you mean exctly?
<emilio> khush_: when I say any selector I mean anything that targets pseudo-elements, so just `::before::marker`-like selectors and `::before>>=::marker`
<emilio> RESOLVED: The pseudoElement argument to animate() takes any pseudo-element selector, and selects the first matching pseudo-element like querySelector()
<vmpstr> emilio: can we resolve to make it consistent for getComputedStyle and similar
<flackr> +1
<khush_> +1
<emilio> Rossen_: as part of this or in a separate issue?
<emilio> emilio: Ideally while we're at it, but happy to defer
<emilio> Rossen_: let's have it in a separate issue
<oriol> For getComputedStyle there is https://github.com/w3c/csswg-drafts/issues/4456