Re: [csswg-drafts] Mixing :is() (or equivalent) with pseudo-elements (#9702)

The CSS Working Group just discussed `Mixing :is() (or equivalent) with pseudo-elements`, and agreed to the following:

* `RESOLVED: Resolve on behavior for nesting, and thinking about non-nesting later`
* `ACTION: Emilio to file issue about specificity`

<details><summary>The full IRC log of that discussion</summary>
&lt;kbabbitt> miriam: I want to see this happen<br>
&lt;kbabbitt> TabAtkins: we've explicitly excluded putting pseudo elements inside :is for a while<br>
&lt;kbabbitt> ... this is for various selector data model reasons<br>
&lt;kbabbitt> ... big one is that :is is a pseudo class which is simple selector, and simple selectors do nothing but filter<br>
&lt;kbabbitt> ... can always take the things matched by a couple of simple selectors, intersect them, and that's what you get when you combine them together<br>
&lt;kbabbitt> ... if we allowed pseudo elements inside :is, that stops being tryue<br>
&lt;kbabbitt> ... you can have .foo which selects all .foo, add :is::before<br>
&lt;kbabbitt> ... and suddenly set of elements is not a subset of .foo<br>
&lt;kbabbitt> ... it's a completely different set, the befores<br>
&lt;kbabbitt> ... and that's weird<br>
&lt;kbabbitt> ... however people want to be able to do that because it's useful<br>
&lt;kbabbitt> ... both directly in :is and indirectly via nesting<br>
&lt;kbabbitt> ... useful to split slector and resolve differently<br>
&lt;kbabbitt> ... so I have a proposal for how to slightly alter the semantics of selectors to make this possible to do<br>
&lt;kbabbitt> ... in :is and in nesting<br>
&lt;kbabbitt> ... so that all of the nesting cases work more naturally<br>
&lt;kbabbitt> ... example that doesn't work well:<br>
&lt;TabAtkins> .foo { ::before, ::after { :hover { color: red; } } }<br>
&lt;kbabbitt> ... that example does not work because, while we let first 2 work okay via special case<br>
&lt;miriam> (I think those all need `&amp;`)<br>
&lt;kbabbitt> ... as soon as you go past that, before and after get shoved into internal :is<br>
&lt;kbabbitt> ... and that makes the innermost nested selector invalid<br>
&lt;TabAtkins> .foo { &amp;::before, &amp;::after { &amp;:hover { color: red; } } }<br>
&lt;kbabbitt> ... doesn't match anything<br>
&lt;kbabbitt> ... so the suggested change is, before you match a complex selector unit<br>
&lt;kbabbitt> ... i.e. compound selector plus pseudo elements<br>
&lt;kbabbitt> ... (thing between combinators)<br>
&lt;kbabbitt> ... we grow the set of matched elements by adding all pseudo elements that are...<br>
&lt;TabAtkins> A > B:is(::before) > C<br>
&lt;emilio> But does that even work? ::before and ::after don't support :hover: data:text/html,&lt;style>:root::before{ content: "foo"; } :root::before:hover { color: red }}&lt;/style><br>
&lt;kbabbitt> ... in that example, ignore whether they go left or right, equivalent meaningfully<br>
&lt;kbabbitt> ... start with elements that match A, combinator takes us to children<br>
&lt;kbabbitt> ... now we add to that set all pseudo elements of A children<br>
&lt;kbabbitt> ... then we execute the B:is(::before)<br>
&lt;kbabbitt> ... that will chop down the list of possible elements to things just matching that<br>
&lt;kbabbitt> ... then before we move on, we will remove any pseudos that were not explicitly matched by that selector<br>
&lt;oriol> emilio, ::before:hover is supposed to work per the spec, https://drafts.csswg.org/selectors-4/#pseudo-element-states<br>
&lt;kbabbitt> ... that last step is required because that selector unit might not have had a pseudo in there, could be :hover applying to a bunch of elements<br>
&lt;kbabbitt> ... can't keep those in list for compat reasons<br>
&lt;kbabbitt> ... a number of psuedo classes do work on pseudo elements<br>
&lt;kbabbitt> ... so, this means my nesting example would work<br>
&lt;kbabbitt> ... there are a few limitations<br>
&lt;emilio> q+<br>
&lt;kbabbitt> ... listed in issue<br>
&lt;astearns> q+<br>
&lt;TabAtkins> .foo:is(*, ::before, ::after)<br>
&lt;kbabbitt> ... this selector ^<br>
&lt;kbabbitt> ... worked in the old webkit matches<br>
&lt;kbabbitt> ... would match .foo, .foo::before, .foo::after<br>
&lt;kbabbitt> ... doesn't match in todays world and will continue to not match<br>
&lt;kbabbitt> ... because pseudoes are supposed to be re-orderable<br>
&lt;kbabbitt> astearns: why does that rule invalidate your example?<br>
&lt;emilio> `::before.foo`<br>
&lt;kbabbitt> TabAtkins: there are no ::before pseudos that are also .foo<br>
&lt;lea> q+<br>
&lt;kbabbitt> ... that is not only illegal syntactically but will not match<br>
&lt;kbabbitt> ... will continue to not match<br>
&lt;kbabbitt> emilio: but it matches now?<br>
&lt;kbabbitt> TabAtkins: no<br>
&lt;kbabbitt> ... only matches .foo, not .foo::before or ::after<br>
&lt;kbabbitt> ... that selector is illegal right now<br>
&lt;romain> q+<br>
&lt;kbabbitt> ... won't match what webkit-matches would have matched<br>
&lt;astearns> q-<br>
&lt;lea> q-<br>
&lt;kbabbitt> ... secondly, building on that same thing<br>
&lt;TabAtkins> :hover:is(::before) and :is(::before):hover<br>
&lt;kbabbitt> ... simple selectors in a compound are always reorderable<br>
&lt;kbabbitt> ... these 2 selectors need to be identical<br>
&lt;kbabbitt> ... they are in all cases today and should continue to be<br>
&lt;kbabbitt> ... but that means that these 2 selectors...<br>
&lt;TabAtkins> :hover::before and ::before:hover<br>
&lt;romain> q-<br>
&lt;kbabbitt> ... which are indeed distinct things and select different things, only 1 can be the meaning of those other 2<br>
&lt;kbabbitt> ... my proposal selects one of these<br>
&lt;kbabbitt> ... the latter<br>
&lt;kbabbitt> ... a before which is hovered<br>
&lt;kbabbitt> ... not the before of a hovered element<br>
&lt;ntim> I wouldn't expect :hover:is(::before) and :is(::before):hover to be the same<br>
&lt;kbabbitt> astearns: here we're defining new behavior<br>
&lt;lea> Would that change the meaning of .foo { &amp;:hover { &amp;::before {} } }?<br>
&lt;kbabbitt> emilio: that's channging currint behavior?<br>
&lt;kbabbitt> TabAtkins: no<br>
&lt;lea> `.foo { &amp;:hover { &amp;::before {} } }`<br>
&lt;kbabbitt> ... the 2 I listed without :is do work today, select distinct elements<br>
&lt;kbabbitt> ... but the 2 that use :is are illegal today<br>
&lt;lea> q+<br>
&lt;kbabbitt> ... giving them meaning, both equal to second one<br>
&lt;kbabbitt> ... those are the only places where this I believe gives potentially unintuitive results<br>
&lt;astearns> q+<br>
&lt;lea> Or, if not, would it become illegal once you turned it into `.foo, .bar { &amp;:hover, &amp;:focus { &amp;::before, &amp;::after {} } }`?<br>
&lt;kbabbitt> ... in all other cases this lets pseudos be used in is and gives obvious answers for all these work<br>
&lt;romain> q+<br>
&lt;astearns> ack emilio<br>
&lt;kbabbitt> emilio: I'm not quite fond of this proposal<br>
&lt;miriam> q+<br>
&lt;ntim> +1 to emilio<br>
&lt;kbabbitt> ... it feels like, especially making hover before mean the same as before hover seems super intuitive to me<br>
&lt;kbabbitt> TabAtkins: if you replace :hover with .foo does it make more sense?<br>
&lt;kbabbitt> emilio: no, I don't know why reordering preserves the meaning<br>
&lt;kbabbitt> ... point is you want to preserve that, within a sinple selector, reordering is important<br>
&lt;kbabbitt> ... vs doing intuitive thing which I think would be, hover before selects the before of hovered element, before hover does something different<br>
&lt;kbabbitt> miriam: that argument makes sense until you add :is<br>
&lt;kbabbitt> ... the is makes them the same thing<br>
&lt;kbabbitt> emilio: so when you add ...<br>
&lt;miriam> ::before:is(:hover)<br>
&lt;kbabbitt> oriol: if you have before and hover without is, they'll be different<br>
&lt;miriam> and :hover:is(::before)<br>
&lt;kbabbitt> ... when you add is, reordering them will ?<br>
&lt;kbabbitt> emilio: don't think that makes sense<br>
&lt;kbabbitt> ... hover before should not be different from before hover<br>
&lt;kbabbitt> miriam: I think they should be, 'is' says theyre the same thing<br>
&lt;kbabbitt> ... not the before on the hover, the ...<br>
&lt;kbabbitt> emilio: that doesn't make sense to me<br>
&lt;kbabbitt> ... I get it in that you're using :is<br>
&lt;kbabbitt> ... but that's so confusing<br>
&lt;kbabbitt> ... also not what authors would expect.<br>
&lt;kbabbitt> ... if I have a complex sector, before after, &amp;::before &amp;::after<br>
&lt;kbabbitt> ... behave the same as if<br>
&lt;kbabbitt> miriam: distinction will be if it has the &amp; or not<br>
&lt;oriol> q+<br>
&lt;kbabbitt> emilio: in general, pseudos in my mental model are basically a combinator<br>
&lt;kbabbitt> TabAtkins: correct<br>
&lt;kbabbitt> emilio: which means making this work is annoying<br>
&lt;miriam> q-<br>
&lt;kbabbitt> ... but if you look at it that way, isn't :is ... guess if you do .foo descendant .bar then ... you're not selecting anything hover<br>
&lt;kbabbitt> ... feels really annoying<br>
&lt;kbabbitt> ... wouldn't expect that behavior at all<br>
&lt;astearns> ack lea<br>
&lt;TabAtkins> :hover:is(> .bar) and :is(> .bar):hover<br>
&lt;kbabbitt> lea: was about to say +1<br>
&lt;kbabbitt> ... but this reordering thing is giving me pause<br>
&lt;kbabbitt> ... might have misunderstood, questions in IRC<br>
&lt;lea> 1. `.foo { &amp;:hover { &amp;::before {} } }`<br>
&lt;kbabbitt> ... would that change how it works given it would be composed with is?<br>
&lt;kbabbitt> TabAtkins: no that would work fine<br>
&lt;kbabbitt> lea: you said foo hover is before<br>
&lt;TabAtkins> equivalent to :is(.foo:hover)::before<br>
&lt;kbabbitt> ... would be equivalent to ???<br>
&lt;kbabbitt> ... doesn't that mean it would change?<br>
&lt;kbabbitt> TabAtkins: the stuff higher in nesting list gets wrapped in pretend :is<br>
&lt;kbabbitt> ... if you invert these, that would give different behavior than you might expect<br>
&lt;kbabbitt> ... as written, equivalent to foo hover before<br>
&lt;lea> `.foo { &amp;::before { &amp;:hover {} } }`<br>
&lt;kbabbitt> lea: so if you had this<br>
&lt;kbabbitt> TabAtkins: that would be equivalent to:<br>
&lt;TabAtkins> ::before:is(.foo:hover)<br>
&lt;ntim> s/???/:is(::before):hover<br>
&lt;kbabbitt> ... not that<br>
&lt;TabAtkins> :is(.foo::before):hover<br>
&lt;kbabbitt> ... that<br>
&lt;kbabbitt> lea: so hover is on before itself?<br>
&lt;kbabbitt> TabAtkins: yes<br>
&lt;kbabbitt> lea: same result is same?<br>
&lt;kbabbitt> TabAtkins: no, hover on foo vs hover on before<br>
&lt;kbabbitt> lea: you still have a pseudo in there<br>
&lt;kbabbitt> TabAtkins: this entire thing is confusing by default, I know<br>
&lt;kbabbitt> ... if we end up not resolving here, that's fine<br>
&lt;kbabbitt> ... I need to fix this problem somehow<br>
&lt;miriam> the first becomes :is(.foo:hover)::before<br>
&lt;kbabbitt> ... I tried another way and everyone hated it<br>
&lt;kbabbitt> lea: any cases where an is through nesting does something different based on nesting?<br>
&lt;miriam> the second becomes :is(.foo::before):hover<br>
&lt;kbabbitt> TabAtkins: sometimes hopefully not often<br>
&lt;kbabbitt> lea: that's worrying<br>
&lt;kbabbitt> ... second example<br>
&lt;lea> `.foo, .bar { &amp;:hover, &amp;:focus { &amp;::before, &amp;::after {} } }`<br>
&lt;kbabbitt> ... based on answer to the first, does that change?<br>
&lt;kbabbitt> TabAtkins: no, it's valid today and does what you expect, won't change<br>
&lt;kbabbitt> ... will only give new results to selectors that don't select pseudos<br>
&lt;kbabbitt> ... i.e. pseudo in middle of nesty<br>
&lt;kbabbitt> lea: problem is once we do this we can't make them work right way<br>
&lt;kbabbitt> TabAtkins: trying to find *a* way to make them work<br>
&lt;emilio> q+<br>
&lt;emilio> ack astearns<br>
&lt;plinss> q+<br>
&lt;kbabbitt> astearns: is the motivation for this entirely nesting and the bare is behavior just a side effect?<br>
&lt;kbabbitt> TabAtkins: yes<br>
&lt;kbabbitt> astearns: no use case for bare is?<br>
&lt;kbabbitt> TabAtkins: there's use cases but not solving for this solving for nesting<br>
&lt;kbabbitt> astearns: any back compat issues having some of these either nested or bare is things with pseudos in someone's stylesheet doing nothing suddenly working?<br>
&lt;kbabbitt> TabAtkins: maybe, hopefully not<br>
&lt;kbabbitt> astearns: does this fall out of the fact that we defined nesting by referencing is?<br>
&lt;kbabbitt> ... and if so, can we instead redefine nesting to use an ish-is like thing<br>
&lt;kbabbitt> ... but sever the tight connectoin between them?<br>
&lt;lea> +1 astearns, was wondering about this too<br>
&lt;ntim> :almost-is()<br>
&lt;kbabbitt> TabAtkins: does somewhat fall out of the semantics defined in terms of is<br>
&lt;kbabbitt> ... don't thnk we can define in other terms to get around this iwhtout either getting back to cominatorial problem<br>
&lt;lea> q+<br>
&lt;kbabbitt> astearns: wondering whetehr we can say, for purpose of nesting, this is the extra behavior you get with pseudos<br>
&lt;kbabbitt> TabAtkins: maybe<br>
&lt;kbabbitt> ... would be very frustrating if you could only express certain selectors via nesting<br>
&lt;kbabbitt> astearns: that's fair<br>
&lt;plinss> q-<br>
&lt;romain> `.foo:is(*, ::before, ::after)`<br>
&lt;astearns> ack romain<br>
&lt;kbabbitt> romain: bit confused about one example, in irc<br>
&lt;kbabbitt> ... don't see why that doesn't work<br>
&lt;romain> `.foo:is(.bar, ::before, ::after)`<br>
&lt;kbabbitt> .. I do but also worry that this second example won't work<br>
&lt;kbabbitt> ... is it wildcards, or anything in pseudo won't work?<br>
&lt;kbabbitt> TabAtkins: first one with wildcard totally works<br>
&lt;kbabbitt> ... will match .foo elements only<br>
&lt;kbabbitt> ... second one will match .foo.bar elements only<br>
&lt;kbabbitt> romain: none of the pseudos will match?<br>
&lt;kbabbitt> TabAtkins: correct ,because no pseudo matches .foo<br>
&lt;kbabbitt> romain: think that's surprising<br>
&lt;kbabbitt> ... mixing pseudos in doesn't work<br>
&lt;kbabbitt> TabAtkins: agree, this is my second try to fix this<br>
&lt;kbabbitt> romain: that's my main issue with this proposal, it's also very surprising<br>
&lt;kbabbitt> miriam: this proposal fixes this?<br>
&lt;TabAtkins> my previous idea was `.foo = (.bar, ::before, ::after)`<br>
&lt;kbabbitt> emilio: it's meant to<br>
&lt;kbabbitt> miriam: my understanding was that's the initial problem &amp; what we're trying to fix<br>
&lt;kbabbitt> romain: what TabAtkins was saying &amp; what I was understanding, you can use pseudos in is, can't mix them<br>
&lt;kbabbitt> TabAtkins: no right now pseudos in is are dropped<br>
&lt;kbabbitt> romain: with proposal they become valid<br>
&lt;kbabbitt> TabAtkins: yes<br>
&lt;kbabbitt> romain: but only match with only pseudos or only classes<br>
&lt;kbabbitt> TabAtkins: yes<br>
&lt;kbabbitt> ... [another case that works I missed]<br>
&lt;kbabbitt> romain: like astearns's thinking, if we let go of is, is there more we can do?<br>
&lt;kbabbitt> ... cases written with nesting aren't ambiguous<br>
&lt;kbabbitt> ... but when written with is, become invalid<br>
&lt;kbabbitt> ... maybe there's more there<br>
&lt;kbabbitt> astearns: also not sure<br>
&lt;astearns> ack oriol<br>
&lt;kbabbitt> oriol: also share concerns about implications for :is being a bit confusing<br>
&lt;kbabbitt> ... along lines of what astearns was saying<br>
&lt;kbabbitt> ... first not the case that &amp; in nesting is defined in spec in terms of is<br>
&lt;kbabbitt> ... just that definition happens to match same behavior<br>
&lt;kbabbitt> ... impls use some kind of alias internally<br>
&lt;kbabbitt> ... but that doesn't have to be the case per spec<br>
&lt;kbabbitt> ... could say &amp; will match elements OR pseudos<br>
&lt;kbabbitt> ... don't see that this would introduce any combinatorial explosion<br>
&lt;kbabbitt> ... with just this change ... impls will not be able to reuse is<br>
&lt;lea> +1 oriol<br>
&lt;kbabbitt> ... but at first glance doesn't seem like a big problem to me<br>
&lt;kbabbitt> ... not just asking around this direction, want to propose it, seems simpler<br>
&lt;kbabbitt> TabAtkins: wouldn't cause a combinatorial explosion, correct<br>
&lt;kbabbitt> ... would cause that some selectos could only be written with nesting, would like to avoid<br>
&lt;kbabbitt> ... want a syntax that lets us expres ssame things with and without nesting<br>
&lt;TabAtkins> .foo { ::before, ::after { :hover { color: red; } } }<br>
&lt;kbabbitt> oriol: I htink it's fine if that's the case<br>
&lt;kbabbitt> ... maybe not ideal but preferable to making is very confusing<br>
&lt;kbabbitt> ... could always extend to is in the future<br>
&lt;kbabbitt> ... or some other syntax<br>
&lt;kbabbitt> astearns: agree it would be nice to express same things nesting vs not<br>
&lt;kbabbitt> ... but only if non-nested version is ergonomic and would get use<br>
&lt;kbabbitt> TabAtkins: example I gave earlier would be totally valid to turn on in nesting but not normal selectors<br>
&lt;kbabbitt> astearns: if non-nesting way of expressing it is so weird no one will ever use it. would be okay to have it be expressible nested only<br>
&lt;kbabbitt> miriam: can be expressed without single selector<br>
&lt;kbabbitt> TabAtkins: any nested selector if you want to expand out, it's fine<br>
&lt;astearns> q?<br>
&lt;astearns> ack emilio<br>
&lt;ntim> I think astearns is saying we shouldn't regress the DX for :is() just to solve the nesting problem, if so +1<br>
&lt;kbabbitt> emilio: is there any reason we cannot make is do what I think is expected behavior?<br>
&lt;plinss> q+<br>
&lt;kbabbitt> ... not preserve order but feels most intuitive?<br>
&lt;kbabbitt> ... as long as you're in the rightmost compound, pseudos only match there<br>
&lt;kbabbitt> ... we don't allow combinators past pseudos<br>
&lt;kbabbitt> ... they don't have descendants that way<br>
&lt;kbabbitt> ... from an impl perspective, does complicate stuff quite a bit<br>
&lt;kbabbitt> ... suddenly selector can match a gazillion pseudos<br>
&lt;kbabbitt> ... but feasible to implement<br>
&lt;astearns> ntim: it’s not so much regressing the entire DX of :is(), I just don’t think it’s worth it to create a hard-to-use version of this with :is()<br>
&lt;kbabbitt> ... I think you would still, other than that weirdness of order representing different things<br>
&lt;kbabbitt> ... (gives examples)<br>
&lt;kbabbitt> ... to me that seems more intuitive for authors<br>
&lt;kbabbitt> ... it's not impossible to implement<br>
&lt;kbabbitt> TabAtkins: the issue becomes that we don't have a concept in selectors ... would lose group of selectors that covers an element<br>
&lt;kbabbitt> ... we rely on the fact that compound selectors can't change subject in a few places e.g. :not<br>
&lt;kbabbitt> emilio: negations and such become tricky, yeah<br>
&lt;kbabbitt> TabAtkins: we rely on the fact thaqt something in CSS lets us only filter, not filter and change<br>
&lt;kbabbitt> ... would no longer have that to reach for at syntactical level<br>
&lt;kbabbitt> ... unfortunate but not killer<br>
&lt;kbabbitt> emilio: not thing is weird ,agree<br>
&lt;kbabbitt> ... any use case?<br>
&lt;kbabbitt> TabAtkins: not pseudo elements, but if pseudos are allowed inside is and can change subject<br>
&lt;kbabbitt> ... why not relative selectors<br>
&lt;kbabbitt> ... (examples)<br>
&lt;kbabbitt> ... at that point we're working on some really shaky foundations<br>
&lt;kbabbitt> ... a before pseudo is a child of an element<br>
&lt;kbabbitt> ... if is can change to child, it should be able to change to any child<br>
&lt;kbabbitt> ... not syntactically ambiguous, would run on same restrictions as nesting<br>
&lt;kbabbitt> ... need combinator at start to trigger<br>
&lt;kbabbitt> ... but if we're going in for a penny, might as well go in for a pound<br>
&lt;kbabbitt> ... use cases for selecting an element and one of its children<br>
&lt;miriam> q?<br>
&lt;kbabbitt> ... can do with nesting<br>
&lt;TabAtkins> .foo { &amp;, &amp; > .bar {...}}<br>
&lt;kbabbitt> emilio: thinking about ...<br>
&lt;kbabbitt> TabAtkins: this nesting example is totally fine<br>
&lt;astearns> ack lea<br>
&lt;kbabbitt> ... being able to express that with is, why not?<br>
&lt;kbabbitt> lea: I think the top priority is that nesting needs to have expected semantics in evrey case<br>
&lt;kbabbitt> ... nice to have multiple ways to express but lower priority<br>
&lt;kbabbitt> ... if we ship this, will always violate principle of least surprise<br>
&lt;kbabbitt> ... is there a subset of cases where it does what author expects?<br>
&lt;kbabbitt> ... I think I came up with cases where even terminal pseudos didn't work, not sure<br>
&lt;kbabbitt> ... I wonder if there's any subset where what TabAtkins is describing is expected<br>
&lt;kbabbitt> ... maybe scope down to that<br>
&lt;kbabbitt> ... and continue to keep other cases as invalid until we find a way to deal with them correctly<br>
&lt;kbabbitt> ... I was also thinking along the lines of what astearns said<br>
&lt;kbabbitt> ... maybe we can internally rewrite how &amp; works<br>
&lt;kbabbitt> ... maybe another path is to see if some limited expansion would prevent combintorial explosion<br>
&lt;astearns> ack plinss<br>
&lt;kbabbitt> plinss: kind of chasing a red herring and conflating too many things here<br>
&lt;kbabbitt> ... nesting being defined with invisible is, should be considered an implementation detail<br>
&lt;lea> +1 plinss<br>
&lt;kbabbitt> ... nesting should just work as if a simple substitution<br>
&lt;kbabbitt> ... combinational explosions okay, that might be behavior you get<br>
&lt;kbabbitt> TabAtkins: minus specificity<br>
&lt;kbabbitt> ... other than that I agree<br>
&lt;kbabbitt> plinss: if we have a problem here with impl detail of nesting, we shouldn't fix that by changing behavior of is<br>
&lt;kbabbitt> ... don't have a problem with changing behavior with is<br>
&lt;kbabbitt> ... if you allow pseudos, you should allow combinators, since a pseudo is a combinator<br>
&lt;kbabbitt> emilio: if it has the outcome of also fixing nesting ...<br>
&lt;kbabbitt> plinss: if it also fixes a way of impling nesting, awesome<br>
&lt;kbabbitt> ... don't need to redefine<br>
&lt;kbabbitt> TabAtkins: What I'm hearing is decent appetite in WG to make nesting work better<br>
&lt;romain> +1<br>
&lt;kbabbitt> ... even if there's some selectors that can't be written without it<br>
&lt;kbabbitt> ... or causing an explosion<br>
&lt;astearns> +1<br>
&lt;kbabbitt> ... and continue to pursue separately how to write without an explosion<br>
&lt;kbabbitt> ... okay<br>
&lt;kbabbitt> astearns: is this what you wanted miriam?<br>
&lt;kbabbitt> miriam: yes<br>
&lt;kbabbitt> astearns: are we taking back to issue or is there a scoped resolution?<br>
&lt;kbabbitt> TabAtkins: Proposed: Go ahead and fix nesting, don't worry about non-nesting yet<br>
&lt;emilio> q+<br>
&lt;astearns> ack emilio<br>
&lt;ntim> PROPOSED: Go ahead and fix nesting for pseudo-elements, don't worry about :is() yet<br>
&lt;kbabbitt> emilio: this has the issue of effectively getting same semantics as keeping is-like substitution<br>
&lt;kbabbitt> ... and making is be able to change target to pseudo element<br>
&lt;kbabbitt> ... would rather investigate that<br>
&lt;kbabbitt> ... don't think it's hard to prototype, kind of annoying<br>
&lt;kbabbitt> TabAtkins: don't have to tie together, I just want them tied together<br>
&lt;lea> TabAtkins: https://codepen.io/leaverou/pen/ByKKByO?editors=1100<br>
&lt;kbabbitt> emilio: maybe we can start ...<br>
&lt;kbabbitt> astearns: does it change your calculation if you account ofr the fact that some aren't happy with the is behavior change?<br>
&lt;kbabbitt> emilio: want to change is to match what you want for nesting<br>
&lt;kbabbitt> ... so you can do (example)<br>
&lt;kbabbitt> TabAtkins: but then I want relative selectors to work<br>
&lt;kbabbitt> emilio: fair but a bigger extension<br>
&lt;kbabbitt> plinss: that's the part I'm not clear on what the result is<br>
&lt;kbabbitt> emilio: I want this...<br>
&lt;emilio> .foo:is(.bar, ::before, ::after) == .foo.bar, .foo::before, .foo::after<br>
&lt;kbabbitt> ... to be the same as ...<br>
&lt;kbabbitt> ntim: I disagree with that<br>
&lt;kbabbitt> emilio: why?<br>
&lt;kbabbitt> ... isn't that what people want?<br>
&lt;kbabbitt> ntim: .foo is not a before pseudo<br>
&lt;kbabbitt> emilio: don't you want combinators there?<br>
&lt;TabAtkins> (this is the :-webkit-matches() behavior)<br>
&lt;kbabbitt> [crosstalk]<br>
&lt;emilio> .foo:is(.bar, > .baz, > .bar)<br>
&lt;kbabbitt> plinss: if we put a combinator in is, what does that mean?<br>
&lt;kbabbitt> ... does combinator go before thing that is is or after?<br>
&lt;kbabbitt> emilio: what I typed<br>
&lt;kbabbitt> TabAtkins: yeah that should work<br>
&lt;miriam> q+<br>
&lt;kbabbitt> emilio: would be equivalent to...<br>
&lt;emilio> `.foo:is(.bar, > .baz, > .bar) == .foo.bar, .foo > .baz, .foo > .bar`<br>
&lt;kbabbitt> ntim: why do we want to overload is? create a new pseudo class?<br>
&lt;miriam> q-<br>
&lt;kbabbitt> emilio: maybe but if we introduce that concept for nesting may as well<br>
&lt;kbabbitt> TabAtkins: if we do this in pseudo space, no reason not to put it in is<br>
&lt;kbabbitt> ntim: maybe :with?<br>
&lt;kbabbitt> ... would make more sense as you read it<br>
&lt;kbabbitt> ... .foo isn't a before pseudo element<br>
&lt;kbabbitt> ... and isn't whatever overload<br>
&lt;kbabbitt> emilio: is this only about naming of is?<br>
&lt;kbabbitt> ntim: yes<br>
&lt;kbabbitt> emilio: what about where?<br>
&lt;kbabbitt> TabAtkins: :is is not meant to be read as "argments are things before"<br>
&lt;kbabbitt> ... it's "I'm selecting something that's one of these'<br>
&lt;kbabbitt> plinss: if you give me that explanation and write what emilio did<br>
&lt;kbabbitt> ... the thing you're selecting is a .baz that is descendant of something that's also .foo<br>
&lt;kbabbitt> ... so it's .foo.baz, not .foo > .baz<br>
&lt;kbabbitt> TabAtkins: now you're arguing for accepting my idea as stated<br>
&lt;kbabbitt> plinss: trying to get an idea of what combinator means<br>
&lt;kbabbitt> ... emilio's expectation doesn't match mine<br>
&lt;kbabbitt> TabAtkins: what emilio wrote is<br>
&lt;kbabbitt> ... the pseudo element version is what :-webkit-matches did<br>
&lt;kbabbitt> ... if it had a relative selector version as well, it would have same semantics emilio listed<br>
&lt;ntim> I expect: `.foo:is(.bar, > .baz, > .bar)` == `.foo.bar, .baz > .foo , .bar > .foo`<br>
&lt;kbabbitt> ... but we don't have to solve this right now<br>
&lt;kbabbitt> ... could take resolution to fix nesting and figure out how to fix as selector later<br>
&lt;kbabbitt> plinss: want to clarify that fix nesting means nesting does naive substitution and got combinatorial explosion if that's the result<br>
&lt;kbabbitt> TabAtkins: as much as possible yes<br>
&lt;kbabbitt> emilio: I find it weird because then you need to define what specificity of pseudo being there vs not<br>
&lt;kbabbitt> ... right now is will drop pseudos<br>
&lt;kbabbitt> ... nesting will right now drop pseudos<br>
&lt;plinss> s/nesting does/nesting behaves as/<br>
&lt;kbabbitt> ... and not consider their specificity in there<br>
&lt;kbabbitt> TabAtkins: but if you put pseudos as innermost nested it works fine<br>
&lt;ntim> `.foo:is(> .baz)` reads to me as ".foo which is a child of .baz", so `.baz > .foo`<br>
&lt;kbabbitt> emilio: you're adding a selector that can select elements in a pseudo<br>
&lt;kbabbitt> ... would rather make this work in :is<br>
&lt;kbabbitt> ... don't see any reason not to do it if we're going to have this functionality<br>
&lt;kbabbitt> TabAtkins: agree<br>
&lt;kbabbitt> ntim: not saying we shouldn't express it, should be an issue for later<br>
&lt;kbabbitt> astearns: I think people in the room agree that this should be expressible, just disagree on how to get it done<br>
&lt;kbabbitt> ... we have agreement on how to make it work with nesting<br>
&lt;kbabbitt> emilio: would like to preserve the fact that nesting can be expressed in terms of regular selectors<br>
&lt;kbabbitt> ... answers a lot of questions about how selectors work<br>
&lt;kbabbitt> ... if you have .foo:is(*)before after<br>
&lt;kbabbitt> ... .before after don't contribute to specificity<br>
&lt;kbabbitt> ... with nesting now they do<br>
&lt;kbabbitt> TabAtkins: they're valid but pseudo elements don't<br>
&lt;kbabbitt> TabAtkins: do pseudo elements have specificity? I don't think they do<br>
&lt;kbabbitt> emilio: I think they do, but right now it might not be visible since you can only have 1<br>
&lt;kbabbitt> ... and it only competes with 1 other pseudo<br>
&lt;kbabbitt> ... when we implemented nesting, one thing that came up is that browsers do have some kind of ? specificity and they were getting mixed<br>
&lt;kbabbitt> plinss: I get your desire to have a pseudo class that behaves exactly like this, and support it<br>
&lt;kbabbitt> ... not usre it should be is<br>
&lt;kbabbitt> emilio: not sure it should not be is<br>
&lt;kbabbitt> ... extending where is something new<br>
&lt;kbabbitt> plinss: not saying we ahve to invent something new, doesn't have to be is<br>
&lt;kbabbitt> emilio: guess it depends how you read it<br>
&lt;kbabbitt> ... if I select something that is this or that, that makes sense to me<br>
&lt;kbabbitt> plinss: is and notion of combinators starts confusing what is is<br>
&lt;kbabbitt> ... which is th eis<br>
&lt;kbabbitt> ... is the is before the combinator or is the is after the combinator<br>
&lt;kbabbitt> ... not sure is is the right thing here<br>
&lt;kbabbitt> TabAtkins: should be read as thing after combinator, selecting thing matching argument<br>
&lt;kbabbitt> plinss: you're basically lofting the combinator in front of the thing outside is<br>
&lt;kbabbitt> TabAtkins: no<br>
&lt;kbabbitt> plinss: then what does combinator do?<br>
&lt;kbabbitt> TabAtkins: as if you just threw away other args and just removed the is<br>
&lt;kbabbitt> ntim: that's not how I read it<br>
&lt;kbabbitt> TabAtkins: that's how webkit-matches does it<br>
&lt;kbabbitt> plinss: that interpretation may make sense if you call it matches, not if you call it is<br>
&lt;kbabbitt> emilio: something we need to decide on is, what specificity these pseudos have<br>
&lt;kbabbitt> ... some pseudos have class specificity<br>
&lt;kbabbitt> ... should is have class specificity?<br>
&lt;oriol> Issue about the specificity of pseudo-elements in nesting: https://github.com/w3c/csswg-drafts/issues/9600<br>
&lt;kbabbitt> ... something else?<br>
&lt;kbabbitt> ... that selector can now be matched against ?<br>
&lt;kbabbitt> TabAtkins: class specificity, say what they have<br>
&lt;kbabbitt> emilio: only relative ot other v-ts righ tnow<br>
&lt;kbabbitt> ... needs to be defined in terms of global selector space<br>
&lt;kbabbitt> TabAtkins: what is the specificity of an element midway down a pseudo stack<br>
&lt;kbabbitt> ntim: already defined?<br>
&lt;kbabbitt> TabAtkins: not yet but will become<br>
&lt;kbabbitt> plinss: for a long time there was a restriction on pseudos, did we relax?<br>
&lt;kbabbitt> TabAtkins: yes<br>
&lt;kbabbitt> ntim: vt pseudos have specificity<br>
&lt;emilio> emilio: but only against each other right now<br>
&lt;kbabbitt> [missed]<br>
&lt;kbabbitt> TabAtkins: emilio can you raise that as an issue?<br>
&lt;ntim> emilio: I think we should implement this in :is, but fine<br>
&lt;ntim> astearns: consensus by exhaustion?<br>
&lt;ntim> PROPOSED: Resolve on behavior for nesting, and thinking about non-nesting later<br>
&lt;ntim> scribe+<br>
&lt;kbabbitt> RESOLVED: Resolve on behavior for nesting, and thinking about non-nesting later<br>
&lt;emilio> ACTION: Emilio to file issue about specificity<br>
</details>


-- 
GitHub Notification of comment by css-meeting-bot
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/9702#issuecomment-3531632590 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Friday, 14 November 2025 08:47:09 UTC