Inheritance and cascading in CSS
This is a guide to help people learning CSS to understand how a browser
works out what styles to apply to a particular element.
As we saw in the introduction to CSS, there are lots of ways you can
apply styles to a particular element. When more than one of these
methods applies, how do you know which styles will be applied?
Fortunately, these rules are quite simple, once you know them. This
article tries to explain all. Of course, the best way really to learn
this stuff is to try stuff out and see what happens.
Overview of rules
- Styles can be inherited
from a parent
- Later styles over-rule
earlier styles
- Styles can combine from
different sources
- Style definitions can
use any combination of element, id, classname and modifier
- You can specify an
element with a certain element type AND id and classname(s)
- Styles can apply to
elements nested in a particular way
1. Styles can be inherited from a
parent
Some styles, like font family,
text-alignment etc., are automatically inherited by child elements from
their parent element (i.e. by an element contained inside another one).
Other are not automatically inherited.
Example
<div
style="font-family:serif; border:1px solid red; padding:10px;">
This text will be in a
serif font.
<p>
This text is also in a serif font, because font
is inherited by default.
But the border and padding properties are not
inherited from the parent div.
</p>
</div>
However, you can make
an element inherit styles from its parent.
Example
<div style="font-family:serif; border:1px solid red;
padding:10px;">
This text will be in a
serif font.
<p style="border:inherit;">
Now the
paragraph also has a red border.
Border properties are not inherited by children,
by default, but because I set border to "inherit", it is.
</p>
</div>
2. Later styles over-rule earlier
styles
If you define a style property, and
later define an alternative style property for the same thing, the
later definition over-rules the earlier one.
Example
<style type="text/css">
body {
background-color:yellow;
font-weight:bold;
}
div {
background-color:#afa;
font-weight:normal;
}
</style>
<body>
<p>Some
text here, inherits properties of the body.</p>
<div>
<p>However, the div's rules over-ride the body's rules,
as the div's rules apply later (i.e. nearer to this text in the
document).</p>
</div>
</body>
This also applies when you have a
combination of external stylesheets, on-page styles, and inline styles.
All other things being equal, the styles that are defined latest,
i.e. written nearest to the actual HTML elements and read by the
browser last, will over-rule earlier definitions.
3. Styles can come from different
sources
The styles that are eventually
applied to an element can have been defined in any
combination of the following ways:
- An external stylesheet
- On-page style definitions
- Inline styles
- Inherited from a parent/container
Complex example
styles.css
.frodo {
border:2px dashed red;
}
complex.html
<link href="styles.css" type="text/css" rel="stylesheet"
/>
<style type="text/css">
.frodo {
background-color:#fcc;
}
</style>
<div class="frodo" style="font-style:italic;">
Here's some text.
</div>
In the example above, the div with
the class name "frodo" gets its border style from an external
stylesheet, its background-color from styles defined above on the page,
and its font-style from an inline style.
From what we've already seen, if the
later styles set any of the same properties as the previously-defined
ones, they would overwrite the previous styles.
4. Style definitions can use any
combination of element, id, classname and modifier
The basic ways of applying a style to
an element are by virtue of its
- HTML element type
- HTML element type
modifier
- id property
- or its classname(s)
I'll explain what each of these
means, and how & when you should use them.
HTML element type
As we covered in the Introduction to CSS,
you can define styles to apply to HTML elements of a certain type, all
the way from the body to little list
items.
In CSS, this is written as, e.g.:
table {
margin:10px;
background-color:#fff;
}
This will apply a space of 10px
around every HTML table, and make them all have a white background -
unless over-ruled by other styles.
HTML element type modifier
There are only a few of these, and
the only ones that are really useful and that work on all browsers are
the modifieres to the anchor (link) tag <a>.
Anchor tags have 4 modifiers:
- a:link
- Doesn't really do anything; just
applies to an anchor that really is a link.
- a:visited
- Used for styling a visited link.
- a:hover
- Applies when you hover your mouse
over the link.
- a:active
- Applies when you have the mouse
button down on a link.
Note that it's good practice to apply
any of these modifiers in the order above. I don't know why, but it'll
ensure they work as expected on different browsers. (I use the
mnemonic: "LoVe HA!" to remember it.)
Example
<style type="text/css">
a, a:link {
color:blue;
text-decoration:none;
}
a:visited {
color:#666;
}
a:hover, a:active {
color:red;
text-decoration:underline;
}
</style>
<a href="css-inheritance-cascade.php">
I am a link to this page,
so should look "visited".</a>
<a href="nofile">
I am a
link to a non-existent file, so should look "unvisited".</a>
ID
An HTML element may have one ID
(unique identifier) property, e.g. <form
id="searchform">. And there should be only one element on a page
with a particular ID.
To assign styles to an element
through its ID, the styles must be defined in CSS (either on the page,
or in a separate CSS document), and indicated by the element's id
prefixed with a hash/pound sign (#).
Example
<style
type="text/css">
#thing {
color:red;
}
</style>
<div id="thing">
This text is red,
because it is part of the element with the id "thing".
</div>
Classname(s)
Applying styles by classname can get
more complicated than using an element's ID, because:
- There can be more than one element
with the same class, and;
- An element may have more than one
class.
Example
<style type="text/css">
.makegrey {
background-color:#ddd;
font-weight:normal;
}
.bigfont {
font-size:1.5em;
font-weight:bold;
}
</style>
<div class="makegrey bigfont">
This div is grey, because it has
the class "makegrey".
Its text is also big and bold, because the div also has the class
"bigfont".
</div>
<div class="bigfont makegrey">
This version also has both classes,
however the font is not bold because the class names are reversed.
Because the second class (makegrey) sets the font-weight to normal, it
over-rides the bold setting of the first class (bigfont).
</div>
5. You can specify an element with
any combination of id, class and element
You can apply styles to an element
using id, classnames, element, and modifier in any combination.
Example
<style type="text/css">
#someid { background-color:#666; }
.class1 { color:#fff; }
.class2 { font-weight:bold; }
div { border:1px solid blue; }
a { font-style:italic; }
a:link { text-decoration:underline; }
</style>
<div id="someid"
class="class1 class2">
<a href="#">
This text inherits all the styles above - each a
different way..
</a>
</div>
6. Styles can apply to elements
nested in a particular way
You can define styles to apply to
particular kinds of elements nested within (or a child of) other
particular kinds of elements. For example:
- Any div that is inside another div
- A list item (<li>)
that is a child of an unordered list (<ul>)
- An anchor (<a>)
that is a child of a list item that is a child of an unordered list
with the id "links"...
To specify nesting, you list the
element definitions separated by a space. Here's how I'd define the
specifications above:
- div div
{styles here...}
- ul li
{styles here...}
- ul#links li a
{styles here...}
All I've done is list the parent (or
grandparent) elements in order of placement in the HTML document
(highest first), concluding with the target element I want to be
affected.
Note: Elements defined in this way
don't have to be directly inside the
parent/ancestor elements. There can be other elements in between, so
long as the elements are nested in the order specified.