Skip to content

Greediness of selectors with combinators [selectors-4] #9605

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

Closed
Rolf-B opened this issue Nov 16, 2023 · 3 comments
Closed

Greediness of selectors with combinators [selectors-4] #9605

Rolf-B opened this issue Nov 16, 2023 · 3 comments
Labels
Closed as Question Answered Used when the issue is more of a question than a problem, and it's been answered.

Comments

@Rolf-B
Copy link

Rolf-B commented Nov 16, 2023

This is not an issue, but I'd like a clarification.

Assume a (dummy) HTML like this: <a>a1</a> <b>b1-1</b> <b>b1-2</b> <a>a2</a> <b>b2</b> <a>a3</a> <b>b3</b>.

Now, I want the b1 elements to be highlighted when the mouse hovers on a1. But not b2 or b3. And the number of b elements after an a element is variable. I created this css rule pair to achive that:

a:hover ~ b { background-color:yellow; }
a:hover ~ b ~ a ~ b { background-color:inherit; }

This works, because the second rule matches the first a element behind the a:hover element.

My question is: Is this behavior specified? Or is it implementation dependent? Because - as in regex patterns, there could be a greedy oder non-greedy matching. The ~ a ~ part of the second selector could match a2 (non-greedy) or a3 (greedy).

To be clear: I ask if the non-greediness of combinators is specified, and where. I don't look for better html or css - the problem occurred for me in a more complex situation where changing the markup is not an option.

@Loirooriol
Copy link
Contributor

a:hover ~ b can match any b which is a later sibling of some a:hover. It can be the 1st such thing, the last, or whatever. All will match. Then a:hover ~ b ~ a matches both your a2 and a3.

BTW, I think CSS Cascade 6 plans to allow something like

@scope-siblings (a:hover) to (a) {
  b { background-color:yellow; }
}

@tabatkins
Copy link
Member

Yup, absolutely well-specified. There is no sense of "greediness" in the same way that regexes work; instead, each combinator just resolves to all appropriate elements. In this case, it works like:

  • start with all possible elements: a1, b1-1, b1-2, a2, b2, a3, b3
  • a:hover filters the set: a1 (presumably)
  • ~ transforms the set to all following siblings: b1-1, b1-2, s2, b2, a3, b3
  • b filters the set: b1-1, b1-2, b2, b3

That's your first selector; the second continues from there:

  • ~ again transforms the set to the following siblings of each element: b1-2, a2, b2, a3, b3 (there's significant overlap here - a2, for instance, is the following sibling of both b1-1 and b1-2)
  • a filters the set: a2, a3
  • ~ transforms the set to all following siblings: b2, a3, b3
  • b filters the set: b2, b3

And that's why you see the behavior you observe.

@Rolf-B Rolf-B closed this as completed Nov 17, 2023
@Rolf-B
Copy link
Author

Rolf-B commented Nov 17, 2023

Ah yes, I need to think set based. Thank you very much.

@Loirooriol Loirooriol added the Closed as Question Answered Used when the issue is more of a question than a problem, and it's been answered. label Nov 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Closed as Question Answered Used when the issue is more of a question than a problem, and it's been answered.
Projects
None yet
Development

No branches or pull requests

3 participants