Once a browser has parsed a document and constructed a document tree Open in a New Window, it must assign a weight to the rules for each element.

While it may not seem simple, the rules of the cascade are specific in terms of which declaration wins out when considering conflicting declarations from multiple locations.

Conflict resolution is the key. If multiple rules apply to a certain selector (possibly from different locations), then which rule is actually used? The browser follows these three rules of the cascade to arrive at its verdict.

#1 - Assimilate All Declarations

Collection of conflicting rules
h1+p {color:#360;} #huron p {color:#960;} .lake {color:#00F;} p.lake {color:#0F0;} p {color:#603;} div div p {color:#F00;} div p.lake {color:#0CC;}

First, the browser reads all of the rules and declarations in all of the 5 possible style sheet locations. It gathers declarations that relate to the same selector. For example, the browser gathers all P declarations together. They will be sorted and prioritized a little later.

When all P declarations are grouped, certain P definitions may have a greater priority (precedence) than other P definitions defined elsewhere. The cascade sorts this out!

This meets the first rule of the cascading order:

"Find all declarations that apply to the element and property in question..."

#2 - Calculate Weight and Origin

The primary method used for sorting conflicting rule declarations is based on the weight and origin of a rule.

On the previous page we covered style sheet order which connects to the origin of a rule. Next we delve into weight derived from specificity. More details on weight are also outlined on the next page which describes the !important directive.

#3 - Determine Specificity

Selectors sorted by weight
p = 001 h1+p = 002 div div p = 003 .lake = 010 p.lake = 011 div p.lake = 012 #huron p = 101

Once all declarations pertaining to a specific selector are grouped together, each declaration in that grouping is prioritized based on its specificity -- how specific each declaration's selector is. The more specific a selector is, the more weight it is given. Selectors with a higher weight are given a higher precedence.

Declarations are assigned a weight based on an "A|B|C" numbering scheme. The total weight of a selector is determined by concatenating - or joining - separate numbers. This number is not produced by addition. The value of A is concatenated with the value of B, which is then concatenated with the value of C to determine the actual weight of any one selector. This may seem strange and convoluted, but it does make sense. A given weight might be 3, or 13, or 113 based on the weighting described below. The higher the number, the more weight is assigned to a declaration.

A = How many IDs are contained in the selector?

IDs are of the highest priority, and if a declaration includes an ID then the A-number value is increased by one. If the selector includes two IDs, then its weight is 2.

#sidebar { color: blue; }

In the example above, there is one ID so the value immediately jumps to 100.

#sidebar #menu { color: blue; }

In the example above, there are 2 IDs, so the value is 200.

For each ID, add 1 to the leftmost A-number; e.g., 1XX or 2XX or 3XX.

IDs have the most weight!

- - - - -

B = How many classes, pseudo-classes, and other attributes are contained in the selector?

In the example below, there is a single class. This adds 1 to the middle B-number of the weighting scheme. The weight of this declaration is 010.

.example { color: green; }

In the example below, there is a pseudo-class within a class, thus the weight here is 020... two total classes.

.example:first-child { color: green; }

For each class or attribute, add 1 to the middle B-number: X1X or X2X

- - - - -

C - How many elements are named in the selector?

The more elements there are, the greater the specificity.

In the example below, there is one tag or element. This adds 1 to the right C-number making the specificity 001.

td { color: green; }

In the example below there are 3 elements so the specificity is 003:

tr td em { color: green; }

For each element name, add 1 to the right C-number: XX1 or XX2

Note: the universal selector ( * ) gets a value of 0 (zero).

- - - - -

D - Ignore pseudo-elements.

A pseudo-element does not add any weight to the selector to which it is attached.

p:first-letter = p = 001 div:first-line = div = 001 .tip:before = .tip = 010

Some other examples from the W3C

* {} /* a=0 b=0 c=0 -> specificity = 0 */ LI {} /* a=0 b=0 c=1 -> specificity = 1 */ UL LI {} /* a=0 b=0 c=2 -> specificity = 2 */ UL OL+LI {} /* a=0 b=0 c=3 -> specificity = 3 */ H1+*[REL=up] {} /* a=0 b=1 c=1 -> specificity = 11 */ UL OL LI.red {} /* a=0 b=1 c=3 -> specificity = 13 */ LI.red.level {} /* a=0 b=2 c=1 -> specificity = 21 */ #x34y {} /* a=1 b=0 c=0 -> specificity = 100 */

At first this may all seem like way too much eggheaded stuff. While you don't necessarily have to memorize it, at least make a mental note that it is explained in the Stylin' book on pages 58-59 for future reference. You may be surprised at how often you find yourself using this information to make a particular rule 'win.'

Something else to keep in mind: if you are ever faced with a style that doesn't work even after confirming that there are no syntax errors, remember that the cause might be the specificity of another style overriding the one you're working on.

Next we will discuss the weight of !important rule declarations and the balance of power between you (the web page author) and the people who view your web pages (users).

References