28: Inheritance and Cascade
11th October 2012: Material moved to webplatform.org
The Opera web standards curriculum has now been moved to the docs section of the W3C webplatform.org site. Go there to find updated versions of these docs, and much more besides!
12th April 2012: This article is obsolete
The web standards curriculum has been donated to the W3C web education community group, to become part of a much bigger educational resource. It is constantly being updated so that it remains current with modern web design practices and technologies. To find the most up-to-date web standards curriculum, visit the web education community group Wiki. Please make changes to this Wiki yourself, or suggest changes to Chris Mills, who is also the chair of the web education community group.
Introduction
Inheritance and the cascade are two fundamental concepts in CSS. Everyone who uses CSS needs to understand them. Fortunately, they aren’t very difficult to grasp, although some of the details may be a bit hard to remember.
The two concepts are closely related, yet different. Inheritance is associated with how the elements in the HTML markup inherit properties from their parent (containing) elements and pass them on to their children, while the cascade has to do with the CSS declarations being applied to a document, and how conflicting rules do or don’t override each other.
I will look closely at both concepts in this article. Inheritance is probably an easier concept to grasp, so I’ll start with that, then progress to the intricacies of the cascade. Download the source code for the examples in this article; the zip contains the finished CSS and HTML, as well as the initial HTML template for you to work with as you go through the examples.
The contents of this article are as follows:
Inheritance
Inheritance in CSS is the mechanism through which certain properties are passed on from a parent element down to its children. It’s quite similar to inheritance in genetics, really. If the parents have blue eyes, their children will probably have blue eyes, too.
Not all CSS properties are inherited, because it doesn’t make sense for some of them to be. For instance, margins are not inherited, since it’s unlikely that a child element should need the same margins as its parent. In most cases common sense will tell you which properties are inherited and which aren’t, but to be really sure you need to look up each property in the CSS 2.1 specification property summary table.
Why inheritance is useful
Why does CSS have an inheritance mechanism then? The easiest way to answer that is probably to consider what it’d be like if there was no such thing as inheritance. You would have to specify things like font family, font size and text colour individually—for every single element type.
Using inheritance, you can for example specify the font properties for the html
or body
elements and
they will be inherited by all other elements.
You can specify background and foreground colours for a specific container element and the foreground colour will
automatically be inherited by any child elements in that container.
The background colour isn’t inherited, but the initial value for background-color
is
transparent
, which means the parent’s background will shine through.
The effect is similar to what you’d get if the background colour were inherited, but consider what would happen if background images were inherited!
Every child would have the same background image as its parent and the result would look like a jigsaw puzzle put together by someone with a serious drug problem, since the background would “start over” for each element.
How inheritance works
Every element in an HTML document will inherit all inheritable properties from its parent except the root element (html
), which doesn’t have a parent.
Whether or not the inherited properties will have any effect depends on other things, as you shall see later on when I talk about the cascade. Just as a blue-eyed mother can have a brown-eyed child if the father has brown eyes, inherited properties in CSS can be overridden.
An example of inheritance
-
Copy the following HTML document into a new file in your favourite text editor and save it as inherit.html.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Inheritance</title> </head> <body> <h1>Heading</h1> <p>A paragraph of text.</p> </body> </html>
If you open the document in your web browser you will see a rather boring document displayed according to your browser’s default styling.
-
Create a new empty file in your text editor, copy the CSS rule below into it, and save the file as style.css in the same location as the HTML file.
html { font: 75% Verdana,sans-serif; }
-
Link the style sheet to your HTML document by inserting the following line before the
</head>
tag.<link rel="stylesheet" type="text/css" href="style.css">
-
Save the modified HTML file and reload the document in your browser. The font will change from the browser’s default (often Times or Times New Roman) to Verdana. If you don’t have Verdana installed on your computer, the text will be displayed in the default sans serif font specified in your browser settings.
The text will also become smaller; only three quarters of what it was in the unstyled version.
The CSS rule we specified applies only to the
html
element. We didn’t specify any rules for headings or paragraphs, yet all the text now displays in Verdana at 75% of the default size. Why? Because of inheritance.The
font
property is a shorthand property that sets a whole number of font-related properties. We’ve only specified two of them—the font size and the font family—but that rule is equivalent to the following:html { font-style: normal; font-variant: normal; font-weight: normal; font-size: 75%; line-height: normal; font-family: Verdana,sans-serif; }
All of those properties are inherited, so the
body
element will inherit them from thehtml
element and then pass them on to its children—the heading and the paragraph.But wait a second! There’s something fishy going on with the inheritance of font size, isn’t there? The
html
element’s font size is set to 75%, but 75% of what? And shouldn’t the font size of thebody
be 75% of its parent’s font size, and the font sizes of the heading and the paragraph should be 75% of that of thebody
element, surely?The value that is inherited is not the specified value—the value we write in our style sheet—but something called the computed value. The computed value is, in the case of font size, an absolute value measured in pixels. For the
html
element, which doesn’t have a parent element from which to inherit, a percentage value for font size relates to the default font size set in the browser. Most contemporary browsers have a default font size setting of 16px. 75% of 16 is 12, so the computed value for the font size of thehtml
element will probably be 12px. And that is the value that is inherited bybody
and passed on to the heading and the paragraph.(The font size of the heading is larger, because the browser applies some built-in styling of its own. See the discussion about the cascade, below.)
-
Add two more declarations to the rule in your CSS style sheet:
html { font: 75% Verdana,sans-serif; background-color: blue; color: white; }
-
Save the CSS file and reload the document in your browser.
Now the background is bright blue and all the text is white. The rule applies to the
html
element—the whole document—whose background will be blue. The white foreground colour is inherited by thebody
element and passed on to all children ofbody
—in this case the heading and the paragraph. They don’t inherit the background but it will default totransparent
, so the net visual result will be white text on a blue background. -
Add another new rule to the style sheet, and save and reload the document:
h1 { font-size: 300%; }
This rule sets the font size for the heading. The percentage is applied to the inherited font size—75% of the browser default, which we have assumed to be 12px—so the heading size will be 300% of 12px, or 36px.
Forcing inheritance
You can force inheritance—even for properties that aren’t inherited by default—by using the inherit
keyword. This should be used with care, however, since Microsoft Internet Explorer (up to and including version 7) doesn’t support this keyword.
The following rule will make all paragraphs inherit all background properties from their parents:
p {
background: inherit;
}
With shorthand properties you can use inherit
instead of the normal values. You have to use shorthand for everything or nothing—in longhand you can’t specify some values and use inherit
for others, because the values can be given in any order and there is no way to specify which values we want to inherit.
Forcing inheritance isn’t something you need to do every day. It can be useful to “undo” a declaration in a conflicting rule, or to avoid hardcoding certain values. As an example, consider a typical navigation menu:
<ul id="nav">
<li><a href="/">Home</a></li>
<li><a href="/news/">News</a></li>
<li><a href="/products/">Products</a></li>
<li><a href="/services/">Services</a></li>
<li><a href="/about/">About Us</a></li>
</ul>
To display this list of links as a horizontal menu, you could use the following CSS:
#nav {
background: blue;
color: white;
margin: 0;
padding: 0;
}
#nav li {
display: inline;
margin: 0;
padding: 0 0.5em;
border-right: 1px solid;
}
#nav li a {
color: inherit;
text-decoration: none;
}
Here the background colour of the whole list is set to blue in the rule for #nav
. This also sets the foreground colour to white, and this is inherited by each list item and each link. The rule for the list items sets a right border, but doesn’t specify the border colour, which means it will use the inherited foreground colour (white). For the links we’ve used color:inherit
to force inheritance and override the browser's default link colour.
Of course I could just as well have specified the border colour as white and the links’ text colour as white, but the beauty of letting inheritance do the job is that you now have only one place to change the colours if you decide to go with another colour scheme.
The cascade
CSS means Cascading Style Sheets, so it shouldn’t come as a surprise that the cascade is an important concept. It’s the mechanism that controls the end result when multiple, conflicting CSS declarations apply to the same element. There are three main concepts that control the order in which CSS declarations are applied:
- Importance
- Specificity
- Source order
I will look into these concepts below, one by one.
Importance is most … er … important. If two declarations have the same importance, the specificity of the rules decides which one will apply. If the rules have the same specificity, then source order controls the outcome.
Importance
The importance of a CSS declaration depends on where it is specified. The conflicting declarations will be applied in the following order; later ones will override earlier ones:
- User agent style sheets
- Normal declarations in user style sheets
- Normal declarations in author style sheets
- Important declarations in author style sheets
- Important declarations in user style sheets
A user agent style sheet is the built-in style sheet of the browser. Every browser has its default rules for how to display various HTML elements if no style is specified by the user or designer of the page. For instance, unvisited links are usually blue and underlined.
A user style sheet is a style sheet that the user has specified. Not all browsers support user style sheets, but they can be very useful, especially for users with certain types of disabilities. For instance, a dyslexic person can have a user style sheet that specifies certain fonts and colours that help reading.
Opera allows you to specify user stylesheets by going to Tools (or the Opera menu on the Mac) > Preferences… > Advanced tab > Content, clicking on the Style Options… button, then pointing to your user style sheet in the My style sheet text field inside the Display tab of this dialog box. You can also specify if you want the user style sheet to override the author (web designer’s) stylesheet in the Presentation tab, and even add a button into the user interface that allows you to switch between the user and author style sheet. To do this, OK out of the Preferences… menu completely, then right- or Ctrl-click somewhere on the Opera browser interface, select Customize… > Buttons tab > Browser view, and drag the Author Mode button somewhere on to one of your toolbars.
An author style sheet is what we normally refer to when we say “style sheet”. It’s the style sheet that the author of the document (or, more likely, the site’s designer) has written and linked to (or included).
Normal declarations are just that: normal declarations.
The opposite is important declarations, which are declarations followed by an !important
directive.
As you can see, important declarations in a user style sheet will trump everything else, which is logical. That dyslexic user might, for instance, want all text to be displayed in Comic Sans MS if he finds that font easier to read. He could then have a user style sheet containing the following rule:
* {
font-family: "Comic Sans MS" !important;
}
In this case, no matter what the designer specified, and no matter what the browser’s default font family is set to, everything will be displayed in Comic Sans MS.
The default browser rendering will only apply if those declarations aren’t overridden by any rules in a user style sheet or an author style sheet, since the user agent style sheet has the lowest precedence.
To be honest, most designers don’t have to think too much about importance, since there’s nothing we can do about it. There is no way we could know if a user has a user style sheet defined that will override our CSS. If they do, they probably have a very good reason for doing so, anyway. Still, it’s good to know what importance is and how it may affect the presentation of our documents.
Specificity
Specificity is something every CSS author needs to understand and to think about.
It can be thought of as a measure of how specific a rule’s selector is.
A selector with low specificity may match many elements (like *
which matches every element in the
document), while a selector with high specificity might only match a single element on a page (like
#nav
that only matches the element with an id
of nav
).
The specificity of a selector can easily be calculated, as we shall soon see. If two or more declarations conflict for a given element, and all the declarations have the same importance, then the one in the rule with the most specific selector will “win”.
Specificity has four components; let’s call them a, b, c and d. Component “a” is the most distinguishing, “d” the least.
Component “a” is quite simple: it’s 1 for a declaration in a style
attribute, otherwise it’s 0.
Component “b” is the number of id
selectors in the selector (those that begin with a #
).
Component “c” is the number of attribute selectors—including class selectors—and pseudo-classes.
Component “d” is the number of element types and pseudo-elements in the selector.
After a bit of counting, we can thus string those four components together to get the specificity for any rule.
CSS declarations in a style
attribute don’t have a selector, so their specificity is always 1,0,0,0.
Let’s look at a few examples—after this it should be quite clear how this works.
Selector | a | b | c | d | Specificity |
---|---|---|---|---|---|
h1 | 0 | 0 | 0 | 1 | 0,0,0,1 |
.foo | 0 | 0 | 1 | 0 | 0,0,1,0 |
#bar | 0 | 1 | 0 | 0 | 0,1,0,0 |
html>head+body ul#nav *.home a:link | 0 | 1 | 2 | 5 | 0,1,2,5 |
Let’s look at the last example in some more detail. You get a=0 since it’s a selector, not a declaration in a style
attribute.
There is one ID selector (#nav
), so b=1.
There is one attribute selector (.home
) and one pseudo-class (:link
), so c=2.
There are five element types (html
, head
, body
, ul
and a
), so d=5.
The final specificity is thus 0,1,2,5.
It’s worth noting that combinators (like >
, +
and the white space) do not affect a selector’s specificity. The universal selector (*
) has no input on specificity, either.
Also worth noting is that there is a huge difference in specificity between an id
selector and an attribute selector that happens to refer to an id
attribute. Although they match the same element, they have very different specificities. The specificity of #nav
is 0,1,0,0 while the specificity of [id="nav"]
is only 0,0,1,0.
Let’s look at how this works in practice.
-
Start by adding another paragraph to your HTML document.
<body> <h1>Heading</h1> <p>A paragraph of text.</p> <p>A second paragraph of text.</p> </body>
-
Add a rule to your style sheet to make text in paragraphs have a different colour:
p { color: cyan; }
-
Save both files and reload the document in your browser, and there should now be two paragraphs with cyan text.
-
Set an
id
on the first paragraph, so you can target it easily with a CSS selector.<body> <h1>Heading</h1> <p id="special">A paragraph of text.</p> <p>A second paragraph of text.</p> </body>
-
Add a rule for the special paragraph in your style sheet:
#special { background-color: red; color: yellow; }
-
Save both files and reload the document in your browser to see the now rather colourful result.
Let’s look at the declarations that apply to your two paragraphs.
The first rule you added sets color:cyan
for all paragraphs.
The second rule sets a red background colour and sets color:yellow
for the single element that has the
id
of special
. Your first paragraph matches both of those rules; it is a paragraph and it has the id
of special
.
The red background isn’t a problem, because it’s only specified for #special
.
Both rules contain a declaration of the color
property, though, which means there is a conflict.
Both rules have the same importance—they are normal declarations in the author style sheet—so you have to look at the specificity of the two selectors.
The selector of the first rule is p
, which has a specificity of 0,0,0,1 according to the rules above since it contains a single element type.
The selector of the second rule is #special
, which has a specificity of 0,1,0,0 since it consists of an
id
selector. 0,1,0,0 is much more specific than 0,0,0,1 so the color:yellow
declaration wins and you get yellow text on a red background.
Source order
If two declarations affect the same element, have the same importance and the same specificity, the final distinguishing mark is the source order. The declaration that appears later in the style sheets will “win” over those that come before it.
If you have a single, external style sheet, then the declarations at the end of the file will override those that occur earlier in the file if there’s a conflict.
The conflicting declarations could also occur in different style sheets.
In that case, the order in which the style sheets are linked, included or imported controls which declaration will be applied, so if you have two linked stylesheets in a document head
, the one linked to last will override the one linked to first. Let’s look at a practical example of how this works.
-
Add a new rule to your style sheet, at the very end of the file, like so:
p { background-color: yellow; color: black; }
-
Save and reload the web page. you now have two rules that match all paragraphs. They have the same importance and the same specificity (since the selector is the same), therefore the final mechanism for disambiguating will be the source order.
The last rule specifies
color:black
and that will overridecolor:cyan
from the earlier rule.
Note how the first paragraph isn’t affected at all by this new rule.
Although the new rule appears last, its selector has lower specificity than the one for #special
. This shows clearly how specificity trumps source order.
Summary
Inheritance and the cascade are fundamental concepts that every web designer needs to understand.
Inheritance lets us declare properties on high-level elements and allows those properties to trickle down to all descendant elements. Only some properties are inherited by default, but inheritance can be forced with the inherit
keyword.
The cascade sorts out all conflicts when multiple declarations would affect a given element. Important declarations will override less important ones. Among declarations with equal importance, the rule’s specificity controls which one will apply. And, all else being equal, the source order makes the final distinction.
Exercise Questions
- Is the
width
property inherited? Think about it first—would it make sense?—then look up the correct answer in the CSS specification. - If we add
!important
to thecolor:black
declaration in the last rule in our example style sheet, will this have any effect on the text colour in the first, “special” paragraph? - Which selector is more specific, “
#special
” or “html>head+body>h1+p
”? - What should a user style sheet look like to make our test document display in black Comic Sans MS on a white background, regardless of the author style sheet?
About the author
Tommy Olsson is a pragmatic evangelist for web standards and accessibility, who lives in the outback of central Sweden. He wrote his first HTML document in 1993 and is currently the technical webmaster for a Swedish government agency.
He has written one book so far—The Ultimate CSS Reference (with Paul O’Brien)
This article is licensed under a Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.
Comments
The forum archive of this article is still available on My Opera.