w3c / csswg-drafts

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

[selectors-4] Need to allow stacked pseudo-element selectors in the grammar #3876

Closed tabatkins closed 5 years ago

tabatkins commented 5 years ago

In Lists, we've resolved that ::before and ::after can be set to "display: list-item", thus generating markers. However, per Selectors grammar, it's not valid to then write a selector like ol::before::marker. (You can stack pseudo-classes after your pseudo-element, but not more pseudo-elements.)

This seems unfortunate; if a ::before can generate a marker, you should be able to style that marker.

Additionally, I know that WebKit-derived browsers, at least, do allow pseudo-element stacking, to handle styling some of the UA-specific pseudo-elements.

So, we should change Selectors grammar to allow stacking multiple pseudo-elements in a single compound selector. (Individual grammar restrictions will still restrict what sort of stacks are valid; ::before::before will be an invalid selector, just like ::before:invalid is invalid today even tho ::before:hover is valid.)

Since certain pseudo-classes are reasonable to apply to either of the pseudo-elements in the stack, the two need to be arbitrary interleavable. (For example, ::before:hover::marker.) This gives us a grammar of:

<compound-selector> = [ <type-selector>? <subclass-selector>*
                        [ <pseudo-element-selector> | <pseudo-class-selector> ]* ]!
css-meeting-bot commented 5 years ago

The CSS Working Group just discussed Need to allow stacked pseudo-element selectors in the grammar, and agreed to the following:

The full IRC log of that discussion <dael> Topic: Need to allow stacked pseudo-element selectors in the grammar
<dael> github: https://github.com/w3c/csswg-drafts/issues/3876
<dael> Rossen_: Is TabAtkins on?
<TabAtkins> Will be in a sec
<dael> fantasai: I can take it
<florian> I did not check that TabAtkins did the grammar correctly (I assume he did), but I support the intent.
<dael> fantasai: There were some cases where we had pseudo elements that are pseudo elements of pseudo elements. One is the marker of a before pseudo if that's set as display:list-item
<dael> fantasai: Selectors grammar only allows one in the grammar. We'll have to relax to allow this. Proposal is do it same as pseudo classes applied to pseudo elements. It's generically allow, but disallowed except for certain whitelisted combinations
<dael> fantasai: The generic grammar needs to allow forthe stacking. Proposal here is to do that for pseudo elements so one can allow another to stack after
<dael> amelia: Really a need to make the whitelist or defined at individual level. It could be a valid that doesn't match anything. Example is invalid that doesn't match anyway and wouldn't when on a before or after.
<amelia> s/match anyway/match non-form elements anyway/
<dael> fantasai: Reason to do is b/c at some point in future might allow some combos, but not sure which will become reasonable. better to make them invalid now and only the ones that make sense now are valid. When another combo is reasonable in the future we can say it's now valid and meanssomething.
<dael> fantasai: Don't want a selector that's valid now but matches nothing but 5 years from now it starts matching a bunch of stuff
<dael> Rossen_: Sounds reasonable
<dael> Rossen_: Other points?
<Rossen_> s/whitelist/allow-list/
<dbaron> sounds reasonable to me too, though I'm not sure I could extract all that fro mthe issue
<dael> Rossen_: +1 to dbaron comment. Thanks for making it clear fantasai
<dael> Rossen_: Objections to accepting the issue?
<dael> fantasai: Prop: Generic selector grammar allows stacking pseudo elements and classes. Only certain combos will be made valid, by default everything is invalid
<dael> Rossen_: Objections?
<dael> RESOLVED: Generic selector grammar allows stacking pseudo elements and classes. Only certain combos will be made valid, by default everything is invalid
ExE-Boss commented 5 years ago

Yeah, this is also necessary because of ::part(…) and ::slotted(…), which allow this as well.

Jamesernator commented 5 years ago

Firefox already supports ::slotted(...)::before and such so parsing them isn't webkit unique.

emilio commented 5 years ago

::slotted is different, as it selects elements. Same for ::part

ExE-Boss commented 5 years ago

Yeah, but the way they are currently specified and implemented violates the current <compound‑selector> grammar.

tabatkins commented 5 years ago

Yup, this is a long-needed grammar change to reflect reality. The fact that the Scoping spec explicitly allowed ::slotted()::before even tho it was grammatically invalid per Selectors just shows that we were behind the ball there. ^_^

ExE-Boss commented 5 years ago

Currently, the grammar contains: [ <pseudo-element-selector> <pseudo-class-selector>* ]*, where the wrapping group has * instead of ?, which reads to me as:

  ╭─────────────────────────────────────────────────────────────────────╮
  │                               ╭─────────────────────────────────╮   │
╟─┤                               │ ╭─────────────────────────────╮ │   ├─╢
  │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┱─╯ ╰─┲━━━━━━━━━━━━━━━━━━━━━━━━━┱─╯ │   │
  ╰─┨ <pseudo-element-selector> ┠─────┨ <pseudo-class-selector> ┠───̶╰̶─̶╮̶─╯
   ╭┺━━━━━━━━━━━━━━━━━━━━━━━━━━━┛     ┗━━━━━━━━━━━━━━━━━━━━━━━━━┛     │
   ╰──────────────────────────────────────────────────────────────────╯

Screenshot_2019-11-19 Railroad Diagram Generator - Pseudo‑element selector%0A%09%09)%0A%09)%0A))

Which would indicate support for multiple pseudo elements.

tabatkins commented 5 years ago

...indeed it does. Cool.

ExE-Boss commented 5 years ago

I still think the syntax could be simplified.

NVM, thinking about it, the current system provides an easy‑ish way to get all the pseudo‑classes associated with a given pseudo‑element.