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:
getComputedStyle
in ???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()
withpseudoElt
param.
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
Element
from 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
CSSPseudoElement
is already defined to include theGeometryUtils
mixin.
- Add (only some?) of these extensions to
- Animate them:
- Have
CSSPseudoElement
include theAnimatable
mixin, similar toElement
.CSSPseudoElement includes Animatable;
- Have
- Get their animations:
- Tackled by the
Animatable
mixin 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
pseudoElement
option 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()
withpseudoElt
param, havegetComputedStyle
also accept aCSSPseudoElement
as 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()
↩