The Cascade

The CSS cascade uses selector pattern matching to apply to elements style declarations that have cascaded down through the document from various sources. But when two or more declarations apply to the same element, and set the same property, how does the browser determine which declaration to apply?

By combining importance, origin, specificity, and the source order of the style concerned, the CSS cascade assigns a weight to each declaration. This weight is used to determine exactly, and without conflict, which style declarations should be applied to a specific element: the declaration with the highest weight takes precedence.

The Process of Resolution

The process of resolution employed by the CSS cascade for each property involves these four steps:

  1. For a given property, find all declarations that apply to a specific element.
  2. Sort the declarations according to their levels of importance, and origins.
  3. Sort declarations with the same level of importance and origin by selector specificity.
  4. Finally, if declarations have the same level of importance, origin, and specificity, sort them by the order in which they’re specified; the last declaration wins.

In step one, a User Agent (typically a web browser) finds all the valid declarations for the specific property to be applied to the element in question; to do so, it looks at all the sources that specify CSS styles for the given media type. Declarations can come from three sources: the user agent, the author, and user style sheets.

User agent style sheets are the default sets of declarations applied by the user agent. For example, according to the CSS specification, the default value for the text-decoration property is none, but typically, user agents set this property to underline for a elements. In some user agents, the default settings can be changed; for example, a user might be able to change the default background color, which may change the user agent style sheet.

A user agent may also allow a user to create a customized set of styles to use by default, or for specific documents. This custom style sheet is called a user style sheet. For instance, both Opera and Safari offer a facility that allows the user to select and use a separate style sheet file.

Author style sheets are those that are linked to the document via a link element, specified using a style element within the document’s head element, or specified within an element style attribute (inline styles).

The user agent must search through all the user agent, author, and user style sheets until it has all the style declarations that are available for the property, and applicable to the element in question. The applicability of a declaration is determined by selector pattern matching; a declaration is applied to an element if the declaration’s selector matches the element. If there’s more than one applicable declaration that sets a specific property on an element, the cascade proceeds to step two.

In step two, declarations that set the same property for the same element are sorted by their levels of importance, and their origins. A declaration can have either of two levels of importance: declarations that are appended with the !important statement are called important declarations; declarations that aren’t are called normal declarations. You can read more about !important in !important Declarations.

Declarations are sorted in the following order (from lowest to highest priority):

  1. user agent declarations
  2. normal declarations in user style sheets
  3. normal declarations in author style sheets
  4. important declarations in author style sheets
  5. important declarations in user style sheets

The declaration with the highest priority is applied to the element. If two or more declarations that set the same property for the same element also have the same priority (that is, the same combination of importance level and origin), the cascade proceeds to step three.

In step three, declarations are sorted on the basis of the specificity of their selectors. The specificity of a selector is represented by four comma-separated values, and is calculated by counting the occurrences of different elements in the selector. For example, inline styles have the highest specificity, while element type selectors have the lowest specificity. A complete explanation of the specificity calculation requires more space than is available here; read more about it in Specificity.

The declaration that has the selector with the highest specificity is applied to the element. However, if two or more declarations that set the same property for the same element also have the same levels of priority and specificity, the CSS cascade proceeds to step four.

Step four is the simplest step and makes the final determination about which declaration to apply to the element without ambiguity. The declaration that’s specified last is the one that’s applied to the element—a process that’s often expressed as the latter declaration overwriting the former. A declaration can be overwritten by another within the same declaration block, within the same style sheet, or in another style sheet.

Declarations in external style sheets are specified in the order in which they’re linked to the document. This is true for style sheets linked via the link element as well as those linked via the @import statement. Declarations within the style sheet containing the @import statements will overwrite all of the declarations in the linked style sheets.

Pay careful attention to the order of link and style elements within the document’s head. Declarations in a style element will overwrite those in a style sheet linked via a link element if the style element is specified after the link element. However, it’s a common mistake to assume that declarations in a style element automatically overwrite those in an external style sheet: if a link element is specified after a style element, the declarations in the linked style sheet will in fact overwrite those in the style element.

The conclusion of this whole process is that the CSS property for the element is set. However, you may be wondering about all the properties the CSS cascade doesn’t set. For example, what happens when there’s no applicable declaration to set the color property for an element? How does it get a foreground color? In the absence of such a declaration, some properties are inherited from the parent of the element.1

The alternative to relying on the inheritance mechanism is to use the property value inherit. Doing so ensures that the inherited value is included in the CSS cascade calculations, but be careful when you use inherit, as browser support for this property value is limited in Internet Explorer.2 If a property isn’t set via the CSS cascade, and it’s not inherited, it’s up to the user agent to supply a default value for the property.

The Cascade in Action

Let’s explore the cascade’s effect on a particular element. Consider this HTML fragment:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <style type="text/css">
      body {
        color: #000;
        background-color: #fff;
      }
      #wrap {
        font-size: 2em;
        color: #333;
      }
      div {
        font-size: 1em;
      }
      em {
        color: #666;
      }
      p.item {
        color: #fff;
        background-color: #ccc;
        border-style: dashed;
      }
      p {
        border: 1px solid black;
        padding: 0.5em;
      }
    </style>
  </head>
  <body>
    <div id="wrap">
      <p class="item">
        This is the <em>cascade</em> in
        <a href="#">action</a>
      </p>
    </div>
  </body>
</html>

For the sake of brevity, all the styles affecting this document are specified in a style element in the document’s head so they all have the same levels of importance and origin. Looking at the styles above, what do you expect the border style, font size, and foreground color to be for the p element?

Have a look at Figure 1 and see if you were correct.

Figure 1. The cascade in action An image displaying the text "This is the cascade in action" in
          a gray box with a dashed black border. The text is white except for
          the word "cascade" which is dark gray and italic, and the word
          "action" which is blue and underlined.

As you can see, the border-style is dashed, the font-size is 2em and the color is white. So where did these properties come from?

There are two CSS rules that apply to the p element:

p.item {
  color: #fff;
  background-color: #ccc;
  border-style: dashed;
}
p {
  border: 1px solid black;
  padding: 0.5em;
}

You can see there’s no conflict for the color property; there’s only one applicable declaration, so the color is set to #fff, or white. We do have a conflict for the background-style property, however, because there are two applicable declarations: dashed and solid. The next step, then, is to compare the specificity of the selectors. The selector p.item, has a higher specificity (0,0,1,1) than that of the selector p (0,0,0,1), so the property is set to dashed.

But where does the font-size value come from? There are no explicit declarations that set the font-size for the p element, but font-size is one of the properties that’s inherited from an element’s parent. The div element is the parent to our p element, and the CSS cascade has set its font-size to 2em in response to the rule with the selector #wrap:

#wrap {
  font-size: 2em;
  color: #333;
}

Thus, our p element inherits the font-size value of 2em. If our p element didn’t have an applicable, explicit color declaration, it would have inherited the value #333 from its parent, too.

The em element has a foreground color of #666 because an applicable declaration is present in the code, as shown in the rule below:

em {
  color: #666;
}

Because the em element is a child of our p element, it would have inherited the foreground color #fff had the declaration not been present.

You may also be wondering why the anchor element is a different color and underlined, since we haven’t applied any styling to it, and color is normally inherited from the parent element. In most user agent style sheets, anchor elements are styled blue and underlined, and the cascade applies user agent style sheet styles first. We could of course redefine the anchor’s CSS properties ourselves; as we already know, declarations in an author style sheet will overwrite the same declarations in a user agent style sheet.

As you can see, the cascade works very well, and once you understand where the styles are coming from, you can control them much more easily.

Tip: CSS Inspectors

Many useful tools are available for analyzing the document and identifying exactly where the styles on the page are coming from; they’ll also help you comprehend this subject. One such tool for the Firefox browser is an extension called Firebug. Similar extensions are available for Safari, Opera, and Internet Explorer.

Footnotes

1 You can read more about inheritance in Inheritance.

2 Read more about inherit in The CSS Property Value inherit.

User-contributed notes

ID:
#9
Contributed:
by svenyonson
Date:
Sat, 14 Nov 2009 01:50:02 GMT

A glossary would be helpful on this site ( if it is there, I can't find it ).

i.e. define "User Agent". I'm guessing it is a browser, but it is not obvious. Googling "User Agent" CSS didn't help either.

ID:
#7
Contributed:
by GrandMaster7
Date:
Mon, 03 Mar 2008 14:47:44 GMT

Typo: background-style should be border-style

Related Products