Understanding CSS specificity will help you understand how rules are applied to the elements on your page and allow you greater control over how your page is styled.
Contents
- Getting Specific
- Calculating Specificity
- Rules for Creating Specific Selectors
- Final Words
- References
Getting Specific
You’ve seen that you can apply multiple styles to an HTML element like this:
And you can create individual styles for various elements on the page:
p {
background-color: aliceblue;
}
#first {
background-color: darkgray;
color: yellow;
}
.important {
font-size: 24px;
background-color: red;
color: black;
border: 2px solid black;
}
.box {
border: 1px solid black;
}
A number of rules style the same CSS properties – background-color and color – and final result depends on:
- the priority (or significance) of the selectors
- for selectors with the same priority, the last defined property takes priority.
Which means that the final style rule looks like this
{
/* ID styles have highest priority */
background-color: darkgray;
color: yellow;
/* font-size is only specified in .important,
so it is applied */
font-size: 24px;
/* border in .box is defined after border was
defined in .important, so it gets applied */
border: 1px solid black;
}
This can seem haphazard and you might like to have better control over your CSS style rules – especially if later declarations can override earlier declarations.
We can overcome this by being more specific with our styling rules:
/*
Apply this style to any element which has
id="first" AND class="important"
*/
#first.important {
font-size: 24px;
background-color: red;
color: black;
}
We can get even more specific with the following:
/*
Apply this style to any <p> element which has
id="first" AND class="important"
*/
p#first.important {
font-size: 24px;
background-color: red;
color: black;
}
However, if you created the following rule:
/*
Apply this style to any <p> element which has
a class="important"
*/
p.important {
font-size: 24px;
background-color: red;
color: black;
}
And you applied it to the following code:
You would find that the styles of #first would take priority over the styles in p.important despite p.important appearing to be more specific – after all, it specifies two selectors (<element> and .class) over the single ID selector.
This is because the significance of a rule depends on the specificity of the selector. CSS specificity is calculated using a few straightforward rules.
Calculating Specificity
Specificity is calculated as a string of three values1. Many resources and tutorials show it as a single number like 000 or 130. Some tutorials show it in the form 0-0-0 or 1-3-0 – which is a better representation. I will use the following representation: 0:0:0 or 1:3:0.
The specificity number indicates the total counts of various basic selectors. The universal selector always has a specificity of 0:0:0 – so any selector with a higher specificity will trump it. As with normal numbers, the leftmost digits are more significant than the rightmost digits. Consider the ranking of the following specificities:
- 0:0:1 > 0:0:0
- 0:2:0 > 0:1:0
- 0:2:1 > 0:1:6
- 0:2:5 > 0:2:4
- 1:2:3 > 0:12:7
The specificity number is calculated as the total number of CSS specifiers used for that style rule. The totals are arranged in the following manner:
IDs | .classes and [attributes] | <elements> |
Consider the specificity of the following selectors:
* {
/* specificity = 0:0:0 */
}
p {
/* specificity = 0:0:1 */
}
.class {
/* specificity = 0:1:0 */
}
[attribute] {
/* specificity = 0:1:0 */
}
#id {
/* specificity = 1:0:0 */
}
p.class {
/* specificity = 0:1:1 */
}
ol[reversed] {
/* specificity = 0:1:1 */
}
p#id.class {
/* specificity = 1:1:1 */
}
p#id.class[attribute] {
/* specificity = 1:2:1 */
}
#id[attribute] {
/* specificity = 1:1:0 */
}
.class[attribute] {
/* specificity = 0:2:0 */
}
/*
it looks strange, but this is valid CSS
you can repeat the same selector over and
over to increase its specificity.
It does not work for <elements>, i.e. you
can not do ppp to increase the specificity
for <p> tags.
*/
.class.class.class.class {
/* specificity = 0:4:0 */
}
In each case, you simply add up the total number of basic selectors, put them in the correct location and compare.
Rules for Creating Specific Selectors
- If you specify an HTML element, then it must be at the beginning of the selector. i.e.: p[attribute] not [attribute]p.
- There can be a maximum of 1 HTML element in a specific selector. i.e.: p.class or ul[reversed], but not pspan.class.
- There can be a maximum of 1 #ID in a selector. This is because an element can have at most 1 #ID.
- The order of .class, [attribute], or #ID doesn’t matter. i.e.: #ID.class is equivalent to .class#ID.
- .class, [attribute], and #ID selectors may be repeated to increase their specificity. i.e.: .class has a specificity of 0:1:0, but .class.class has a specificity of 0:2:0.
- You cannot repeat HTML elements. i.e.: pppp or ulul have no meaning and will be ignored by the browser.
- All selectors are written together without spaces between them. i.e.: p.class is not the same as p .class and #id[attribute] is not the same as #id [attribute].2
Final Words
-
You can be very specific about which HTML element to style on a page by stringing together various selectors associated with that element:
- Specificity is calculated by summing and arranging the total number of basic specifiers in each of the following groups:
IDs .classes and [attributes] <elements> - In deciding which styling rule to apply, the rule with the higher specificity is applied.
- If two rules have the same specificity then the last rule defined is applied.
- The universal selector always has a specificity of 0:0:0.
-
There are no spaces between the selectors – it is written as one long expression.
References
-
For now it is three values, in reality there two more values that have higher specificity and can be considered as the fourth and fifth specificity values – they will be covered in a future tutorial.↩
-
The next tutorial will show how spaces between selectors changes the meaning of the selection expression.↩