One of the most fundamental things about CSS properties is that they cascade, which is why the technology is called Cascading Style Sheets. But what does this mean?
Cascading is a method used to resolve potential conflicts between the various different types of style sheet a browser supports, and apply them in order of precedence by who created them, the method used to create the styles, and the types of properties selected.
There are three main types of style sheet supported by all modern browsers. In order of precedence from high to low, they are:
These three sets of style sheets are processed in reverse order. Firstly, the defaults in the web browser are applied to the document. Without these defaults, web pages that don’t use style sheets would look terrible. They include the font face, size, and color; element spacing; table borders and spacing; and all the other reasonable standards a user would expect.
Next, if the user has created any styles to use in preference to the standard ones, these are applied, replacing any of the browser’s default styles that may conflict.
Lastly, any styles created by the current document’s author are applied, replacing any that have been created either as browser defaults or by the user.
Style sheets can be created using three different methods. In order of precedence from high to low, they are:
As inline styles
In an embedded style sheet
As an external style sheet
Again, these methods of style sheet creation are applied in reverse order of precedence. Therefore, all external style sheets are processed first, and their styles are applied to the document.
Next, any embedded styles (within <style>...</style>
tags) are
processed. Any that conflict with external rules are given precedence
and will override them.
Lastly, any styles applied directly to an element as an inline
style (such as <div
style="...">...</div>
) are given the highest
precedence, and override all previously assigned properties.
There are three different ways of selecting elements to be styled. Going from highest to lowest order of precedence, they are:
Referencing by individual ID or attribute selector
Referencing in groups by class
Referencing by element tags (such as <p>
or <b>
)
Selectors are processed according to the number and types of elements affected by a rule, which is a little different from the previous two methods for resolving conflicts. This is because rules do not have to apply only to one type of selector at a time, but may reference many different selectors.
Therefore, a method is needed to determine the precedence of rules that can contain any combination of selectors. This is done by calculating the specificity of each rule by ordering them from the widest to narrowest scope of action.
The specificity of a rule is calculated by creating three-part
numbers based on the selector types in the numbered list above. These
compound numbers start off looking like [0,0,0]
. When processing a rule, each
selector that references an ID increments the first number by 1, so
that the compound number would become [1,0,0]
.
Let’s look at the following rule. It has three ID references
(#heading
, #main
, and #menu
), so the compound number becomes
[3,0,0]
:
#heading, #main, #menu, .text, .quote, .boxout, .news, .comments, p, blockquote { font-family:'Times New Roman'; font-size :14pt; }
Next, the number of selectors that reference a class is placed
in the second part of the compound number. In the current example
there are five selectors in all—.text
, .quote
, .boxout
, .news
, and .comments
—so the number becomes [3,5,0]
.
Finally, all selectors that reference element tags are counted,
and this number is placed in the last part of the compound number. In
our example there are two (p
and
blockquote
), so the final compound
number becomes [3,5,2]
, which is
all that is needed to compare this rule’s specificity with that of any
another.
In cases where there are nine or fewer of each type in a
compound number, you can convert it directly to a decimal number,
which in this case is 352
. Rules
with a lower number than this will have lower precedence, and those
with a higher number will have greater precedence. Where two rules
share the same value, the most recently applied one wins.
Where there are more than nine of a type in a compound number,
you have to work in a higher number base. For example, the compound
number [11,7,19]
doesn’t convert to
decimal by simply concatenating the three parts. Instead, you can
convert the number to a higher base, such as base 20 (or higher if
there are more than 19 of any type).
To do this, multiply out the three parts and add the results like this, starting with the rightmost number and working left:
20 × 19 = 380 20×20 × 7 = 2800 20×20×20 × 11 = 88000 Total in decimal = 91180
If you need to use a higher base, replace the values of 20 on the left with the base you are using. Then, once all the compound numbers of a set of rules are converted from this base to decimal, it is easy to determine the specificity, and therefore the precedence, of each.
Thankfully, the CSS processor handles all of this for you, but knowing how it works will help you to properly construct rules and understand what precedence they will have.
If all this precedence calculation sounds rather complicated, you’ll be pleased to know that in most cases you can usually get by with a simple rule of thumb: in general, the fewer elements that there are to be modified, and the more specific they are, the greater the precedence given to the rule will be.
Where two or more style rules are exactly equivalent in
precedence, by default the most recently processed rule will be the
one that is applied. However, you can force a rule to a higher
precedence than other equivalent rules using the !important
declaration, like this:
p { color:#ff0000 !important; }
When you do this, all previous equivalent settings are
overridden (even ones using !important
), and any equivalent
rules that are processed later will be ignored. So, for example, the
second of the two following rules would normally take precedence, but
because of the use of !important
in
the prior assignment, the second one is ignored:
p { color:#ff0000 !important; } p { color:#ffff00 }
User style sheets can be created for specifying default
browser styles, and they may use the !important
declaration, in which case the
user’s style setting will take precedence over the same properties
specified in the current web page. However, on very old browsers
using CSS1, this feature isn’t supported.