By now it should be clear that there are many ways styles can be applied to an element—from an external style sheet file, from a <style> tag set, and from a style attribute in a tag—and there is the possibility that multiple style rules can easily apply to the same element in a document (intentionally or not). To deal with these issues, the CSS recommendation had to devise a set of rules for resolving conflicts among overlapping styles. These rules are intended primarily for the browser (and other user agent) makers, but if you are designing complex style sheets or are seeing unexpected results in a complex document, you need to be aware of how the browser resolves these conflicts for you.
Conflict resolution is mostly a matter of assigning a relative weight to every rule that applies to a particular element. Rules with the most weight are the ones that most specifically target the element. At the lightweight end of the spectrum is the "nonrule," or default style setting for the document, generally governed by the browser's internal design and sometimes influenced by preference settings (e.g., the base font size for text content). Such a "nonrule" may directly apply to only a high-level object, such as the body element; only by way of inheritance does the default rule apply to some element buried within the content. At the heavyweight end of the spectrum is the style rule that is targeted specifically at a particular element. This may be by way of an ID selector or the ultimate in specificity: a style attribute inside the tag. No run-of-the-mill style rule can override an embedded style attribute.
Between those two extremes are dozens of potential conflicts that depend on the way style sheets are defined for the document. As an example, a browser always has its own default style sheet so that it knows how to render standard elements. Browser preferences (such as viewing in a larger font size) modify those default settings. Some browsers also allow users to apply their own generic style sheets to override the default settings. But what happens when a document arrives with its own settings? Before rendering any style-sheet-capable element, the browser uses the following decision path to determine how that element should be rendered:
Scan the document for any author-specified style declarations that have a selector that matches the element. If the element is not selected by any rules, short-circuit the rest of the decision path and render the element according to the user's style sheet, if present, or the browser's current built-in settings.
Sort all applicable declarations according to weight as indicated by a special !important declaration (see the following section). Declarations marked important are assigned greater weight than unmarked declarations.
Sort declarations again, this time by origin. If the same selector and style declaration is marked !important in both the document and the user's style sheet (if present), give precedence to the user's style (in other words, assign the greatest possible weight to user rules marked !important). For unmarked declarations, assign greater weight to the author's style, followed by the user's style (if present), and then the browser default style.
Now sort the unmarked declarations by the specificity of the rule's selector. The more specific the selector (see the section on selector specificity later in this chapter), the greater the weight assigned to that declaration.
Finally, if more than one declaration is assigned the same weight after previous sorting, sort one last time based on the order in which the rules are defined in the document. The last applicable rule with the greatest weight wins the conflict. Rules defined in multiple imported style sheets are defined in the order of the statements that trigger the import; an @import rule must be positioned before explicit rules in a <style> tag set and therefore carries less weight than the explicit rule; a rule defined in an element's style attribute is the last and heaviest unmarked (i.e., not !important) rule.
You can give an individual declaration within a rule an extra boost in its battle for superiority in the cascading order. When you do this to a declaration, the declaration is called the important declaration; it is signified by an exclamation mark (!)and the word important following the declaration. For example, in the following style sheet, the margin-left attribute for the p element is marked important:
<style type="text/css"> p {font-size:14px; margin-left:2em !important; margin-right:2em} p.narrow {color:red; margin-left:5em; margin-right:5em} </style>
When the document encounters a <p> tag with a class attribute set to narrow, the left margin setting of the less specific <p> tag overrides the setting of the more specific p.narrow class because of the important declaration. Note that this is an artificial example because you typically would not include conflicting style rules in the same style sheet. The important declaration can play a role when a document imports one or more style sheets. If a generic rule for the specific document must override a more specific rule in an imported style sheet, the important declaration can influence the cascading order. A browser that has correctly implemented user style sheets treats a user's !important style declaration as the weightiest style rule. While a page designer might question why the user has the most power in the cascading battle, bear in mind that a user may employ styles tailored to special accessibility needs, such as extra-large font sizes or high-contrast color combinations.
The fourth cascading precedence rule refers to the notion of specificity, or how well a rule selector targets a particular element in a document. The CSS recommendation establishes an unseen, internal ranking system that assigns values to three categories, arbitrarily designated a, b, and c. These categories represent the counts of items within a rule selector, as follows:
For any rule selector, the browser adds up the total for each category and then concatenates the three totals to come up with a specificity value. Table 3-4 displays a sequence of rule selectors in increasing specificity.
Rule selector |
a |
b |
c |
Specificity rating |
---|---|---|---|---|
em |
0 |
0 |
1 |
1 |
p em |
0 |
0 |
2 |
2 |
div p em |
0 |
0 |
3 |
3 |
em.hot |
0 |
1 |
1 |
11 |
p em.hot |
0 |
1 |
2 |
12 |
#hotStuff |
1 |
0 |
0 |
100 |
Browsers use the highest applicable specificity rating value to determine which rule wins any conflict. For example, if a style sheet defines the six rules for em elements shown in Table 3-4 (with the #hotStuff rule being an ID selector), the browser applies the highest relevant specificity rating to each instance of the em element. An element with the tag <em class="hot"> inside an h1 element most closely matches the em.hot rule selector (specificity rating of 11), and therefore ignores all other selectors. But if the same em element is placed inside a p element, the more specific rule selector (p em.hot) wins.
Copyright © 2003 O'Reilly & Associates. All rights reserved.