Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-pseudo-4] should CSSPseudoElement have a pseudo() method? #3836

Closed
heycam opened this issue Apr 17, 2019 · 23 comments
Closed

[css-pseudo-4] should CSSPseudoElement have a pseudo() method? #3836

heycam opened this issue Apr 17, 2019 · 23 comments

Comments

@heycam
Copy link
Contributor

heycam commented Apr 17, 2019

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?

@heycam heycam added the css-pseudo-4 Current Work label Apr 17, 2019
@emilio
Copy link
Collaborator

emilio commented Apr 17, 2019

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.

@heycam
Copy link
Contributor Author

heycam commented Apr 18, 2019

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

@emilio
Copy link
Collaborator

emilio commented Apr 18, 2019

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.

@tabatkins
Copy link
Member

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.

@birtles
Copy link
Contributor

birtles commented Apr 25, 2019

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.)

@tabatkins
Copy link
Member

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

@birtles
Copy link
Contributor

birtles commented Apr 25, 2019

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

@tabatkins
Copy link
Member

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

@heycam
Copy link
Contributor Author

heycam commented Apr 30, 2019

Maybe rename CSSPseudoElement.element to something like parent?

@heycam
Copy link
Contributor Author

heycam commented Apr 30, 2019

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

@birtles
Copy link
Contributor

birtles commented May 2, 2019

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?

@css-meeting-bot
Copy link
Member

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//issues/3836

@Jamesernator
Copy link

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].

@emilio
Copy link
Collaborator

emilio commented Jun 4, 2019

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.

@Jamesernator
Copy link

Jamesernator commented Jun 4, 2019

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>

@lpd-au
Copy link

lpd-au commented Jun 15, 2019

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

@ExE-Boss
Copy link
Contributor

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

@fantasai
Copy link
Collaborator

Agenda+ to consider @lpd-au’s #3836 (comment)

@css-meeting-bot
Copy link
Member

css-meeting-bot commented Jan 20, 2021

The CSS Working Group just discussed should CSSPseudoElement have a pseudo() method? Would it be worth considering having two separate properties, Element element and Element|CSSPseudoElement parent, and agreed to the following:

  • RESOLVED: Use the existing parent function in css pseudo element as returning firrst element ancestor and add an immediate parent that could possibly return a pseudo element
The full IRC log of that discussion <dael> Topic: should CSSPseudoElement have a pseudo() method? Would it be worth considering having two separate properties, Element element and Element|CSSPseudoElement parent
<dael> github: https://github.com//issues/3836#issuecomment-502344378
<dael> florian: Because it is now possible to have pseudo attached to pseudos. In addition to element class having pseudo pseudo element class has apseudo.
<dael> florian: Another question, pseduo element class has an element method that returns originating element. Pseudo on a pseudo do you want originating or parent pseduo?
<dael> florian: Original thought is return the parent. Later proposed we should have both. Element returns originating element, but also have a parent method that returns parent pseudo if there is one and if there isn't returns originating
<dael> florian: Got thumbs up so proposal is accept
<dael> astearns: If it's not nested parent returns nothing?
<dael> florian: Returns same as element
<dael> astearns: First is element ancestor and second is immediatate parent
<dael> florian: Yes
<dael> fantasai: One thought, if we extend to non-tree-abiding parent is not quite the right word. If you select first-letter element parent is the first line or some weird nesting. We could call it parent and say these things are special
<dael> florian: It would be walking up hierarchy step by step. Just need to define weird cases
<dael> fantasai: As long as people say it can be repurposed to not quite a parent it's fine to me. Just wanted to point out it's going to be a bit weird
<dael> astearns: Other opinions?
<dael> astearns: Hearing people in favor
<dael> astearns: Prop: Use the existing parent function in css pseudo element as returning fifrst element ancestor and add an immediate parent that could poss return a pseudo element
<dael> RESOLVED: Use the existing parent function in css pseudo element as returning firrst element ancestor and add an immediate parent that could possibly return a pseudo element

Official Minutes

@fantasai
Copy link
Collaborator

Edits in. I had to add a new section to Selectors 4 also. See
https://drafts.csswg.org/selectors-4/#sub-pseudo-elements
and
https://drafts.csswg.org/css-pseudo-4/#cssom
once it all regenerates.

@frivoal @lpd-au @heycam Let me know if anything seems off, or if the edits seem to correctly reflect what we agreed here. (CSSOM stuff is not my forte, exactly.)

@frivoal
Copy link
Collaborator

frivoal commented Dec 31, 2021

Not an OM expert either, but it looks good to me.

@lpd-au
Copy link

lpd-au commented Jan 9, 2022

This looks great to me, thanks for your work! :)

As a nitpick, I believe it would be helpful to readers for the definition of parent to say "originating element or originating pseudo-element" for the spec reference, but maybe that's redundant and unnecessary since the rest of the definition already points to sub-pseudo-elements... (I'm no expert either!)

@fantasai
Copy link
Collaborator

@lpd-au I think that would downplay the idea that an “originating element” can be either an element or a pseudo-element, i.e. that “originating pseudo-element” is defined as a sub-class of “originating element”. Since the next sentence explicitly mentions the case of having an originating pseudo-element, the intent should be clear from the spec already, so I think we don't particularly need to call it out. At least, that's my thinking. Lmk if that makes sense. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants