Cascading

Cascading Rules

Cascading is the process by which a style system determines which value for each property to apply to each element. There are four rules in the process of cascading.

1. The rule's selector must match the element

For a style rule to apply to an element, its selector must match the element. If there is only one declaration for a given property with a selector that matches an element, then that declaration applies, without question. If multiple declarations match the element, then the declaration that applies is determined by weight and origin, specificity, or order, as explained below.

If there is no declaration for a given property with a selector that matches the element, then the value for that property is set to its default value (as defined in the CSS specification). This default value could be one of three things.

Newer versions of CSS are making it possible to specify explictly more of these defaults. In CSS1, the only thing that a stylesheet could state explicitly was the first possibility above, a value. That is, in CSS1, explicit values were the only defaults that, when overrided, could be returned to the default with a rule higher in the cascade. In CSS2, one can explicitly give the second behavior using the inherit keyword. Perhaps in future versions of CSS it will be possibly to specify that properties inherit from the values of other properties. (Note, however, that the default behavior of the border-*-color properties can be obtained using the shorthand border properties.)

2. Rules are chosen by weight and origin

In a user or an author stylesheet, a declaration may be given the weight !important, by placing !important (with optional whitespace on either side of the !) after the property's value, like this:

body {
  color: black ! important;
  background-color: white!important;
  }

This weight controls the declaration's place in the cascade. Of all the declarations for a given property that match an element, the one that is chosen must be one of those in the highest category in the following list:

  1. Rules in the user stylesheet with weight !important
  2. Rules in the author stylesheet with weight !important (Note: In CSS1, author-important declarations were more important than user-important declarations. This was changed in CSS2. Some browsers support the CSS1 rules. Therefore, authors should avoid using !important so that users with disabilities can still access all pages.)
  3. Rules in the author stylesheet with normal weight
  4. Rules in the user stylesheet with normal weight
  5. Rules in the user agent (UA, i.e., the browser) stylesheet: Even if they do not have an explicit UA stylesheet, browsers are required to act as though all the presentation of HTML (e.g., that headers are large and have margins above and below them) is encoded in a UA stylesheet.

If there are multiple declarations for a given property in the highest of these groups that exists, then the declarations below are used to choose the value that is applied. For example, if there are three author declarations that match a given element (and no user-important or author-important declarations), then specificity (and maybe even order) must be used to find which rule applies.

3. Rules are chosen by the specificity of their selectors

Specificity is a number derived from a rule's selector (in an arbitrary large number base, not in base ten) that tells which declaration is applied. Specificity is used only when multiple rules have selectors that match the element and no rule has the unique heighest weight/origin combination. The specificity is used to determine which rules of those with the highest weight/origin combination of those rules whose selectors match the element.

The specificity of a selector is calculated as follows. It is the number abc where a is the number of id selectors in the selector, b is the number of pseudo-classes and attribute selectors (including class selectors), and c is the number of element names in the selector. An inline style element also has specificity 100 (and is assumed to be after any other rules), but I have proposed that this be changed, partly because browsers treat it as if it had specificity 1000. For example, the following selectors have the specificities given:

Selector Specificity
* 0
h1 1
body table > thead > tr + tr 5
UL LI OL LI OL LI UL LI UL LI UL LI c
.warning 10
table code.usercss 12
div[lang=en][class=warning] > h1[lang=fr] 32
A:link *[alt=""][border=0][class="warning"] 41
#head H1 + P 102

Note that grouping of selectors does not change specificity. If the selector is h3, h4.warn, h5#error, the specificity is still 1 if the element matched is an h3, 11 if the element matched is an h4 with class="warn", and 110 if the element matched is an h5 with id="error".

4. Declarations are chosen by their order

If there are still multiple declarations of the same property that match an element and have the same weight, the same origin, and the same specificity, then the last one wins. This finally determines which value is applied. You may think this one doesn't get used much, but that isn't true. It is often needed so that (for example) pseudo-classes that are not mutually exclusive work correctly. For example, the following doesn't do what is intended:

a:hover { color: red; }
a:link { color: blue; } /* overrides a:hover for unvisited links */
a:visited { color: purple; } /* overrides a:hover for visited links */

The a:hover rule needs to be placed after the other two so that it will cascade over them.

Also, it is often useful to define the same rule twice in one ruleset, for example:

body {
  font: 16px/1.5 "Times New Roman", Times, serif; /* sets a number of
  properties to their default value, including font-size-adjust */
  font-size-adjust: 0.45;
  }

Interaction of CSS and presentational HTML

This section (as is the section on selectors) is based partially on an article I wrote on comp.infosystems.www.authoring.html.

Non-CSS presentational hints are, according to CSS2, translated into the corresponding CSS rules and treated as if they occurred at the beginning of the CSS style sheet with specificity zero. This means that appropriate CSS declarations in the author style sheet always override them (as do !important declarations in the user stylesheet).

However, the important question is what author declarations override them. The answer to this question comes from the way CSS selectors work. Selectors match elements in the document tree. The default (which is often to inherit from the parent) only occurs when no selector matches the element.

Now, what does this mean for non-CSS presentational hints? It means that they can always be overridden by author CSS that acts on the HTML element that provides the presentational hint. For example, the ruleset:

font {
  color: inherit;
  font-size: inherit;
  font-family: inherit;
  }

in an author stylesheet will neutralize all font elements (assuming that "inherit" works, which it doesn't in some browsers.) To do this in a user stylesheet, one would need to use the weight "! important":

font {
  color: inherit ! important;
  font-size: inherit ! important;
  font-family: inherit ! important;
  }

However, styling an element that occurs on the outside of the non-presentational hint will do nothing (since the rule applied by the non-presentational hint overrides the default inheritance), and styling an element inside of it will always have an effect, even if the style is in a UA stylesheet. The rules for handling non-CSS presentational hints only act when CSS selectors match the HTML elements providing the presentational hints. For example, the following 2 statements are true because of the tree structure of the document:

<span style="color: green;">
  <font color="red">
    This text is red.
  </font>
</span>

<font color="red">
  <span style="color: green">
    This text is green.
  </span>
</font>

An example of a situation that *is* affected by the rules for non-CSS presentational hints given in CSS2 is the following:

<font color="red" STYLE="color: green">
  This text is green.
</font>

However, if the user stylesheet contained the rule

font { color: green; }

then what would happen is:

<font color="red">
  This text is red.
</font>

because the non-presentational hint is treated as if it were a CSS rule at the beginning of the author stylesheet, and therefore overrides a rule in the user stylesheet.

Finally (and most importantly), how do the browsers handle this? Does this actually mean anything? Surprisingly, the browsers handle it quite well in its interaction with author stylesheets (interaction with user stylesheets is not quite so good). I wrote a test for this behavior, and MSIE 5 beta 2 passes the test perfectly. Netscape 4.5 has a few bugs with PRE and with body backgrounds, but handles the font face examples fine. (I tested font face, not font color.)


Valid HTML 4.0!

(Up to User Stylesheets Guide, CSS, David Baron)

LDB, dbaron@dbaron.org, 1999-06-15