The Cascade
Try it yourself!View all demos
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:
- For a given property, find all declarations that apply to a specific element.
- Sort the declarations according to their levels of importance, and origins.
- Sort declarations with the same level of importance and origin by selector specificity.
- 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 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):
- user agent declarations
- normal declarations in user style sheets
- normal declarations in author style sheets
- important declarations in author style sheets
- 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.
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.
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:
- #8
- Date:
- Wed, 09 Apr 2008 17:33:12 GMT
- Status:
- This note has not yet been confirmed for accuracy and relevance.
Can the example code be in a larger font size?
- ID:
- #7
- Date:
- Mon, 03 Mar 2008 14:47:44 GMT
- Status:
- This note has not yet been confirmed for accuracy and relevance.
Typo: background-style should be border-style
Add a note
To post a note on this topic, please log in with your SitePoint username and password. If you don't have an account yet, you can create a new account for free.
