Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS combinator precedence?

Is there a precedence to combinators like

a > b ~ c d 

(Note the space between c and d is the descendant combinator)

Or is it just read left-to-right, like

((a > b) ~ c) d 

?

like image 645
mpen Avatar asked Oct 03 '10 21:10

mpen


People also ask

What is the order of precedence of CSS selectors?

Inline CSS has a higher priority than embedded and external CSS. So final Order is: Value defined as Important > Inline >id nesting > id > class nesting > class > tag nesting > tag.

Which CSS level has the highest precedence?

Introduction. This article explains what CSS Precedence Levels are. A CSS precedence level mainly defines the priority of CSS styles that CSS applies to a specific element at the following three levels. Inline styles have the highest priority over the external style and external styles.

What is combinator selector in CSS?

A combinator is something that explains the relationship between the selectors. A CSS selector can contain more than one simple selector. Between the simple selectors, we can include a combinator. There are four different combinators in CSS: descendant selector (space)

What is the main work of combinator in CSS?

A combinator is a way to define the relation between selectors. By using combinators, for example, we can target only child elements of a parent element, or we can target an element followed by another element on the same level and like that. There are 4 types of combinators as: descendant selector (space)


2 Answers

No, there is no notion of precedence in combinators. However, there is a notion of order of elements in a complex selector.

Any complex selector can be read in any direction that makes sense to you, but this does not imply that combinators are distributive or commutative, as they indicate a relationship between two elements, e.g. ancestor descendant and previous + next. This is why the order of elements is what matters.

According to Google, however, browsers implement their selector engines such that they evaluate complex selectors from right to left:

The engine [Gecko] evaluates each rule from right to left, starting from the rightmost selector (called the "key") and moving through each selector until it finds a match or discards the rule.

Mozilla's article, Writing Efficient CSS for use in the Mozilla UI has a section that describes how their CSS engine evaluates selectors. This is XUL-specific, but the same layout engine is used both for Firefox's UI and pages that display in Firefox's viewport. (dead link)

As described by Google in the above quote, the key selector simply refers to the right-most simple selector sequence, so again it's from right to left:

The style system matches rules by starting with the key selector, then moving to the left (looking for any ancestors in the rule’s selector). As long as the selector’s subtree continues to check out, the style system continues moving to the left until it either matches the rule, or abandons because of a mismatch.

Bear in mind two things:

  • These are documented based on implementation details; at heart, a selector is a selector, and all it is intended to do is to match an element that satisfies a certain condition (laid out by the components of the selector). In which direction it is read is up to the implementation; as pointed out by another answer, the spec does not say anything about what order to evaluate a selector in or about combinator precedence.

  • Neither article implies that each simple selector is evaluated from left to right within its simple selector sequence (see this answer for why I believe this isn't the case). What the articles are saying is that a browser engine will evaluate the key selector sequence to figure out if its working DOM element matches it, then if it does, progress onto the next selector sequence by following the combinator and check for any elements that match that sequence, then rinse and repeat until either completion or failure.


With all that said, if you were to ask me to read selectors and describe what they select in plain English, I would read them from right to left too (not that I'm certain whether this is relevant to implementation details though!).

So, the selector:

a > b ~ c d 

would mean:

Select any d element
that is a descendant of a c element
that is a sibling of, and comes after, a b element
that is a child (direct descendant) of an a element.

like image 69
BoltClock Avatar answered Oct 18 '22 12:10

BoltClock


It doesn't matter.

a > b c  

will match the same elements regardless of whether you do it

(a > b) c 

or

a > (b c) 

I think that browsers go right-to-left.

like image 45
Šime Vidas Avatar answered Oct 18 '22 11:10

Šime Vidas