Re: [csswg-drafts] [selectors] Backwards combinators (#12453)

Okay, so first, I'm mildly opposed to this:
* I think it's pretty limited sugar when we have :has()
* I think the consistent "down and forward" direction of selectors is a good thing
* I think the "zig zag" possibilities of this syntax, especially when combining `>>` with `<<` or `~` with `-~`, can be really confusing and unintuitive, where matched nodes can jump past each other rather than "drilling down" between some bounds. (That is, in `A >> B << C`, the final C can be higher in the tree than A, rather than being *between* A and B, which might be expected intuitively. `A C:has(B)` or `C:has(A B)` are instead unambiguous.) Put another way, I think if we can go both directions we need parentheses for grouping, which is what `:has()` implicitly provides.

But I don't understand what the confusion/ambiguity being talked about is. Each combinator is a transform of the matched set, and it doesn't matter whether you do that left or right; the direction just affects what the actual transform function is.

In `A B > C D`, read left to right it's "Find all As. Flatmap to their descendants. Filter for Bs. Flatmap to their children. Find all Cs. Flatmap to their descendants. Filter for Ds. That's the result.". Read right to left it's "Find all Ds. For each D, find their ancestors. Filter for Cs. Flatmap to their parents. Filter for Bs. Flatmap to their ancestors. Filter for As. If there's anything left, the corresponding D is in the result." (And the reason impls do it right to left, obviously, is that "map to ancestors" usually gives far smaller result sets than "map to descendants". Plus some other subtle perf reasons, like matching during tree-building.)

Exactly the same process happens for `A B < C D`, in either direction, it just inverts the transform in the middle: flatmapping to parents in left-to-right, and flatmapping to children in right-to-left.

-------

I agree with Oriol's transforms. If you desugar to pairwise combinators, using `:is()` semantics for the grouping, then combinators are right-associative (and all equal precedence), and `A B < C D` desugars to `:is(:is(A B) < C) D`: A `D`, whose ancestor is a `C`, whose child is a `B`, whose ancestor is an `A`.

-- 
GitHub Notification of comment by tabatkins
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/12453#issuecomment-3046915842 using your GitHub account


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

Received on Tuesday, 8 July 2025 00:09:41 UTC