Csswg-drafts: [css-pseudo-4] should CSSPseudoElement have a pseudo() method?

Created on 17 Apr 2019  Â·  17Comments  Â·  Source: w3c/csswg-drafts

https://drafts.csswg.org/css-pseudo-4/#CSSPseudoElement-interface

You can get to the pseudo-element of an element with Element.pseudo(). But some pseudos are defined to have other pseudos hanging off them, like with ::part(label)::before. Does CSSPseudoElement need its own pseudo() method?

css-pseudo-4

Most helpful comment

Would it be worth considering having two separate properties, Element element and Element|CSSPseudoElement parent?

All 17 comments

I'd much rather not make Element.pseudo() return pseudo-elements which are really other elements like ::slotted or ::part. They can match multiple elements at once I don't know what a sane return value for that would be.

That's a great reason for not doing it for those pseudos. :-) Are there other pseudos where it still might make sense?

You could addres the ::marker that ::before and ::after create themselves... But it'd be weird to be able to target them via this API but not via CSS Selectors.

But it'd be weird to be able to target them via this API but not via CSS Selectors.

I've opened #3876 to discuss that, it is indeed weird.

Even if we don't have pseudo() on CSSPseudoElement itself, provided you can start a CSS animation/transition on the ::marker for a ::before (which I assume will be the case once #3876 is resolved), what should we return as the animation target in that case?

  • Would it be a CSSPseudoElement with type '::before::marker' and element as per an un-stacked pseudo (i.e. the actual originating DOM Element)?
  • Or would it have type '::marker' and element the parent CSSPseudoElement?
  • Or just type '::marker' and the originating DOM Element? (Making it indistinguishable from the ::marker pseudo on the Element.)

Should be the second; it's a ::marker whose originating element is the ::before.

Ok, I guess we need to change the type of CSSPseudoElement.element from Element to (Element or CSSPseudoElement).

Yeah. And add .pseudo() to CSSPseudoElement. ^_^

Maybe rename CSSPseudoElement.element to something like parent?

Also, what's the story for getting computed style of these "stacked" pseudo-elements?

Maybe rename CSSPseudoElement.element to something like parent?

It used to be named that (or parentElement actually), but in #2816 it was pointed out that that was wrong and originatingElement was too long so it became element. In this world of stacked pseudos, maybe parent is actually now correct?

The CSS Working Group just discussed CSSPseudoElement having a pseudo() method, and agreed to the following:

  • RESOLVED: add .pseudo() to CSSPseudoElement once some stacked pseudo combination becomes a valid selector. Adjust .element return type to match.

The full IRC log of that discussion
<fantasai> Topic: CSSPseudoElement having a pseudo() method

<fantasai> AmeliaBR: Seems to make sense to me, if a pseudo-element can have a pseudo-element, then having .pseudo() would make sense

<fantasai> emilio: Have we decided yet how to make those styleable

<fantasai> fantasai: will be stylable with selectors like ::before::marker

<fantasai> emilio: I would wait to add this method until that is allowed

<fantasai> fantasai: So proposal is to add .pseudo() to CSSPseudoElement once stacked pseudo becomes a valid selector

<fantasai> plinss: Side issue of whether to rename .element to .parent

<fantasai> fantasai: Not always a parent

<fantasai> TabAtkins: The full term is "originating element" but that was too long

<fantasai> TabAtkins: So shortened to .element

<fantasai> plinss: Need to reach pseudo-element between you and the element

<fantasai> TabAtkins: Yeah, that's what .element would do

<fantasai> plinss: OK

<fantasai> TabAtkins: When we adopt this, just the return type would be adapted

<fantasai> RESOLVED: add .pseudo() to CSSPseudoElement once some stacked pseudo combination becomes a valid selector. Adjust .element return type to match.

<emilio> github: https://github.com/w3c/csswg-drafts/issues/3836

I personally think .pseudo should be able to return a pseudo-element for any name rather than just the hard coded list of ::marker, ::before and ::after.

Why? Well a pseudo-element is meant to be transparent as to whether or not it points to single element, multiple elements, text nodes, etc. Because of the way they are specified it's only possible to target all such components or none of them in CSS, similarly I think it should work identically with .pseudo that a CSSPseudoElement represents all parts that are used to construct that element.

This would work fine with getComputedStyle too as there's no way to actually style individual parts of pseudo elements. So even if a ::part(foo) corresponded to 50 elements, a ::part(foo) selector can only style all 50 or none of them, so getComputedStyle is consistent (assuming getComputedStyle is not allowed to leak styles out).

Also it'd be nice with reference selectors or similar ideas too as then you could do someElement.pseudo("::part(name)").references = [partStyles].

Well, parts as well as slotted elements can have different styles even if they are the same part or slotted selector, because of rules in and outside the shadow tree respectively, so that just doesn't hold.

Well, parts as well as slotted elements can have different styles even if they are the same part or slotted selector, because of rules in and outside the shadow tree respectively, so that just doesn't hold.

No the elements that comprise of the parts can have different styles, the styles of an element are resolved from its ::part, element, slotted, etc styles. But if you take a .pseudo("::part(bar)") on an element the styles applied via ::part(bar) are necessarily unique just from the fact that there's no way to be more specific then ::part(bar).

getComputedStyle absolutely should not be able to reach into the shadow root and view styles applied by inner style sheets and probably shouldn't be able to know about other ::parts even.

As an example I would expect this to return red even if the rendered color is blue (because getComputedStyle shouldn't be able to reach into shadow roots and violate encapsulation):

<style>
  #foo::part(bar) {
    color: red;
  }
</style>

<div id="foo">
  #shadow-root
    <div part="bar" style="color: blue;"></div>
</div>

<script>
  // Only the resolved styles of the pseudo-element should be considered
  // not the combined styles of the actual elements inside the shadow root
  // as outside code should never be able to know about things like style="..."
  // attributes or so forth that happen from within the shadow root
  getComputedStyle(foo.pseudo("::part(bar)")) === 'red';
</script>

Would it be worth considering having two separate properties, Element element and Element|CSSPseudoElement parent?

@Jamesernator
Except that would violate the way getComputedStyle(…) is currently specified, as the computed style is the actual style used for rendering.

Was this page helpful?
0 / 5 - 0 ratings