start page | rating of books | rating of authors | reviews | copyrights

Book HomeCascading Style Sheets: The Definitive GuideSearch this book

2.8. The Cascade

Through all this, we've skirted one rather important issue: what happens when there are two rules of equal specificity that apply to the same element? How does the browser resolve the conflict?

For example, let's say we have the following rules:

H1 {color: red;}
H1 {color: blue;}

So which one wins? Both have a specificity of 1, so they have equal weight and should both apply. That simply can't be the case, though, because the element can't be both red and blue. It has to be one or the other. But which?

This is where the name "Cascading Style Sheets" finally makes some sense. CSS is based on a method of causing styles to cascade together -- a method that is made possible by the rules of inheritance and specificity, as it happens. The cascade rules are simple enough:

  1. Find all declarations that contain a selector that matches a given element.

  2. Sort by explicit weight all declarations applying to given element. Those rules marked !important are given higher weight than those that are not. Also sort by origin all declarations applying to a given element. There are three origins: author, reader, and user agent. Under normal circumstances, the author's styles win out over the reader's styles. !important author styles win out over important reader styles in CSS1, but in CSS2, !important reader styles are stronger than any other styles. Either author or reader styles will override user agent styles.

  3. Sort by specificity all declarations applying to a given element. Those elements with a higher specificity have more weight than those with lower specificity.

  4. Sort by order all declarations applying to a given element. The later a declaration appears in the style sheet or document, the more weight it is given. Declarations that appear in an imported style sheet are considered to come before all declarations within the style sheet that imports them, and declarations within STYLE attributes come later than those in the document's embedded style sheet.

In order to be perfectly clear about how this all works, let's consider an example that illustrates each of the four cascade steps. The first one is simple enough: find all rules whose selectors match a given element.

Under the second step, if two rules apply to an element, and one is marked !important, then the important rule wins out. Thus:

P {color: gray !important;}

<P STYLE="color: black;">Well, <EM>hello</EM> there!</P>

Despite the fact that there is a color assigned in the STYLE attribute of the paragraph, the !important rule wins out, and the paragraph is gray, as shown in Figure 2-28. This gray is inherited by the EM element as well.

Figure 2-28

Figure 2-28. Sorting styles by their importance

Furthermore, the origin of a rule is considered. If an element is matched by styles in both the author's style sheet and the reader's style sheet, then the author's styles are used. For example, assume that the following styles come from the indicated origins:

P EM {color: black;}    /* author's style sheet */

P EM {color: yellow;}   /* reader's style sheet */

In this case, we have the result shown in Figure 2-29, where the emphasized text is black.

Figure 2-29

Figure 2-29. Sorting styles by origin

As it happens, the browser's default styles -- which are often influenced by its preferences -- are figured into this step. The browser's default styles are the least influential of all. Therefore, if an author-defined rule applies to anchors (e.g., declaring them to be white), then this rule overrides the user agent's defaults. If readers wish to enforce certain rules at all costs, then they must define them in a local style sheet and declare them to be !important, so that they will win out under step 1 of the cascade rules. In this case, though, it will be a case of the reader's styles overriding both the author's and browser's styles due to their importance.

According to the third step, if multiple rules apply to an element, then they should be sorted by specificity, with the most specific rule winning out. For example:

P#bright {color: silver;}
P EM {color: gray;}
P {color: black;}

<P ID="bright">Well, <EM>hello</EM> there!</P>
Figure 2-30

Figure 2-30. Sorting styles by specificity

As we can see from Figure 2-30, the text of the paragraph is silver, except for the EM text, which is gray. Why? Because the specificity of P#bright (101) overrode the specificity of P (1), even though the latter rule comes later in the style sheet. However, the EM text does not inherit the value silver, because it has an explicit rule associated with it, and the rule's specificity (2) overrides the inherited value of silver.

This is not a trivial point. For example, assume that a style sheet has been written such that all text in a toolbar is to be white on black:

#toolbar {color: white; background: black;}

This will work so long as the element with an ID of toolbar contains only plain text. If, however, the text within this element is all hyperlinks (A elements), then the user agent's styles for hyperlinks will take over -- because despite the fact the they're imported, they are explicit style assignments, so they override any inherited values. Usually, this means that they'll be colored blue, since the browser's style sheet probably contains an entry like this:

A:link {color: blue;}

In order to overcome this problem, the author would need to declare:

#toolbar A:link {color: white; background: black;}

By targeting the rule directly to the A elements within the toolbar, the author will get the result shown in Figure 2-31.

Figure 2-31

Figure 2-31. Using contextual selectors to overcome specificity

Lastly, under the fourth step, if two rules have exactly the same weight, origin, and specificity, then the one that occurs later in the style sheet wins out. Thus, let us return to our earlier example, where we find the following two rules in the document's style sheet:

H1 {color: red;}
H1 {color: blue;}

The value of color for all H1 elements in the document will be blue, not red.

Any rule that is contained in the document, having a higher weight than the imported rule, wins out. This is true even if the rule is part of the document's style sheet and not part of an element's STYLE attribute. Consider the following:

P EM {color: purple;}  /* from imported style sheet */

P EM {color: gray;}    /* rule contained within the document */

In this case, the second rule shown, since it is a part of the document's style sheet, will win out over the imported rule.

For the purposes of this rule, styles that are given in the STYLE attribute of an element are considered to be at the end of the document's style sheet, which places them after all other rules. In addition, a STYLE attribute has a weight equivalent to that of an ID selector. Thus, the following code would result in black text, as shown in Figure 2-32:

#hello {color: red;}

<P ID="hello" STYLE="color: black;">Hello there!</P>
Figure 2-32

Figure 2-32. Sorting styles by their position

Here, the weight of the inline style (100) is equal to the weight of the rule #hello (100), so the winner is the rule that occurs later in the document.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.