-
Notifications
You must be signed in to change notification settings - Fork 756
Description
Fun with Pseudos
In light of View Transitions I’ve been playing a lot with pseudo-elements trying to do all sorts of things with them from within JavaScript:
- Access them
- Get info about their position+size
- Animate them
- Get their animations
- Access their styles
Accessing the pseudos themselves is in theory possible through Element.pseudo() but in practice it has no browser support1.
Some of the other features I listed above are made possible in some APIs through means of the pseudoElement option. When working with these it becomes quickly pretty clear that this pseudoElement is an afterthought that was introduced in order to get it to work quickly, instead of fully adopting the existence of CSSPseudoElement. See #4301 for example that chose to add the pseudoElement option to Element.animate instead of embracing CSSPseudoElement.
Since then other APIs have also been monkey-patched to accept a pseudoElement option:
getComputedStylein ???Element.getAnimations()in [view-transitions-2] Add method to get all animations of a ViewTransition object #9908 (comment)
So as for the things I want to do with pseudos this is the current state of affairs:
- Access them: Theoretically using
pseudo()but that has not shipped anywhere. - Get info about their position+size: Not directly possible (you could anchor a real Element to it and then do getBCR on that Element).
- Animate them: Only if they already have animation attached to them that you can hijack
- Get their animations: Theoretically using
Element.getAnimations()but that is not specced yet. You can sniff ’m manually, though. - Access their styles:
getComputedStyle()withpseudoEltparam.
With more and more features leaning on pseudo-elements (select::picker, ::details-content, carousel pseudos, customizable select, etc.) this problem will become more visible to authors.
Making pseudo-elements first-class citizens
Instead of monkey-patching more APIs to accept a pseudoElement, I believe it would be nicer if pseudo-elements becamse first-class citizens of the DOM. All the pieces of the puzzle are there, it’s a matter of putting them together:
- Access them:
- Already specced:
pseudo()which returns aCSSPseudoElement
- Already specced:
- Get info about their position+size:
- Add (only some?) of these extensions to
Elementfrom cssom-view also toCSSPseudoElement - If not all, then at least these would be needed:
partial interface CSSPseudoElement { DOMRectList getClientRects(); [NewObject] DOMRect getBoundingClientRect(); }
- For reference: The
CSSPseudoElementis already defined to include theGeometryUtilsmixin.
- Add (only some?) of these extensions to
- Animate them:
- Have
CSSPseudoElementinclude theAnimatablemixin, similar toElement.CSSPseudoElement includes Animatable;
- Have
- Get their animations:
- Tackled by the
Animatablemixin from the previous point. - Also: undo the resolution from [view-transitions-2] Add method to get all animations of a ViewTransition object #9908 (comment) and remove the
pseudoElementoption fromgetAnimations()(which is safe to do because this is not specced + has not shipped anywhere)
- Tackled by the
- Access their styles:
- In addition to
getComputedStyle()withpseudoEltparam, havegetComputedStylealso accept aCSSPseudoElementas its first argument.- This would also make a nicer solution to [cssom] getComputedStyle for ::before::marker or ::after::marker #4456
- In addition to
Just a starting point
Most likely I’m overlooking a bunch of things and I’m definitely lacking some nuances to some of the many pseudos that would allow/disallow this – so I’m very much looking forward to input on this one.
Footnotes
-
Thankfully I didn’t really need the pseudos directly in my experiments. Because I only needed the animations+effects applied to them, I was able to sniff them out through
document.getAnimations()↩