- From: Tab Atkins Jr. via GitHub <sysbot+gh@w3.org>
- Date: Tue, 12 Dec 2023 23:54:07 +0000
- To: public-css-archive@w3.org
Yeah, I'll give it some more time to percolate, but some variant on my "Second Try" idea is probably what I'm aiming for. Pulling it out to make it easier to find/reference: Problem statement: we'd like the following to be valid: ```css .foo { &, &::before, &::after { &:hover { color: blue; }}} ``` ...and have the obvious result, equivalent to: ```css .foo:hover, .foo::before:hover, .foo::after::hover { color: blue; } ``` Solution: introduce a new combinator, `=`, and a new `<complex-selector-unit>`, the parenthesized list. 1. `=` selector is a no-op combinator; it has no effect on the current set of matched elements. So `.foo = .bar` is the same as `.foo.bar`, `.foo = ::before` is the same as `.foo::before`, etc. 2. `<complex-selector-unit>` currently expressed the `compound selector + pseudo-element" bit of the grammar. It both filters the current matched elements *and* possibly changes the set (just to pseudos, currently), and might do that repeatedly. We add `(<selector-list>)` to the grammar for it. * We just run the selector list on the current set of matched elements, filtering it and potentially changing it (just to pseudos, currently) * The problem statement above could be written as `.foo = (*, ::before, ::after) = :hover {...}`. * This works with other combinators, too: `.foo > (*, ::before)` selects all children of a `.foo` element *and* their before pseudos. * The selectors inside the `()` can be full complex selectors, just like in `:is()`, so `.foo = (.bar *, #baz > *)` selects `.foo` elements that have a `.bar` ancestor or a `#baz` parent. * This is still slightly weaker than Nesting itself; you can't do the equivalent of `.foo { &, & > .bar {...}}` because the current match set (whatever the preceding combinator yielded) is always the subject of the selectors in the paren list. That's probably okay. We'd have to invent a new way to refer to the elements being matched if we wanted to expand that (not `:scope` or `&`, but a secret third way). I dunno, maybe we do need it. * Specificity would have to be the same as `:is()`, to avoid the same sort of "which way did it match" exponential explosion. Nesting can then define itself on top of this: `X { Y {...}}` desugars to `(X) = (Y) {...}`, with just a little extra magic: * `&` refers to the current matched elements (so in the `(Y)` bit, `&` refers to the `(X)` elements, etc). (This expands lists' ability to change the set from just changing to pseudo-elements, to changing to anything potentially.) * Remember that `&` represents the elements (and now, pseudo-elements) matched by the parent selector; it's *not* textual substitution. So `::before { :hover& {...}}` is equivalent to `::before:hover`, not `:hover::before` - the parent selector filters the match set to all the ::before pseudos, then `:hover&` represents elements that are (a) in the parent's match set, and (b) hovered. * The final list keeps "normal" specificity behavior, where it matters which selector actually matched. (This avoids changing the *current* behavior of `.foo, { .bar, #baz {...}}`.) -- GitHub Notification of comment by tabatkins Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/9702#issuecomment-1853046171 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Tuesday, 12 December 2023 23:54:09 UTC