CSS Specificity Decoded
"In specificity lies the answer." - Dalai Lama on CSS
Table of contents
No headings in the article.
Every developer who has ever had to use CSS to style has definitely faced this problem. How does CSS choose which style to apply to an element, provided we have multiple styles for the same element in the CSS file via multiple selectors?
Let's take a closer look at the problem.
The problem
Let's say we write this simple piece of HTML.
Now we want to style this header. For which we write this CSS.
We have two CSS style blocks essentially referring to the same element. They are:
- Apply 'color: blue' to all 'a' i.e link elements.
- Apply 'color: blue' to all 'a' i.e link elements with class 'link-class'.
This is the essence of the problem. Two selectors applied to the same element. Which one wins?
The solution
Answer: The one which is more specific. Intuitively, we know that block 2 is more specific than block 1 since it mentions both the element as well as the class. That's it, that's the entire solution to this problem.
Now let's look at a bit more theory behind specificity, some more specific examples (pun very well intented) and some caveats.
Caveats/Overriding points
- Inline CSS: Inline CSS written beside the HTML file itself overrides other CSS imported from a separate CSS style sheet.
- !important keyword: this keyword, if added to a css property will override all other declarations for this property elsewhere. For eg: background-color: red !important; added to any selector will always prevail over background-color declared anywhere else without !important.
These two things will override all specificity. Note: important! takes precedence over inline CSS.
Calculating specificity score
If we have multiple selectors styling the same element, provided we have no inline CSS and/or important! keywords, we proceed to calculate the specificity score of each selector.The order of specificity calculation is: - ids. - classes, pseudo-classes and attributes. - elements and pseudo-elements.
We will call them score 1, 2 and 3 respectively.
What exactly does this order mean? Each selector (eg: a.link-class[target]) has a specificity score of the format (score 1, score 2, score 3) where score 1, 2, 3 refer to the scores above.
Example: Consider the selector 'a.link-class[target]'. Let us calculate the specificity score for this selector:
1. Score 1: ids = 0 since it has no IDs.
2. Score 2: classes, pseudo-classes and attributes = 2 It has one class i.e link-class and one attribute selector target.
3. Score 3: elements and pseudo-elements = 1 It has only one element i.e a.
The specificity score of the selector is thus = (score 1, score 2, score 3) = (0, 2, 1)
This is how we calculate the specificity score. Now let's see how to use it.
Using specificity score
Consider this HTML and it's corresponding CSS.
We have two selectors pointing essentially to the same element. The specificity score for each is:
- a.link-class[target] = (0, 2, 1) as calculated in the section above.
- a.link-class = (0, 1, 1) -> same as the first selector but no attribute selector so we minus one point from Score 2.
To decide which style will be applied, we compare the two scores.
(0, 2, 1) vs (0, 1, 1)
- Score 1: Both are 0 (equal). So we proceed ahead.
- Score 2: 2 vs 1. 2 is greater so the first specificity wins. We do check calculate any further.
- Score 3: If Score 2 would also have been equal we would have proceeded to check Score 3.
Based on this calculation, we can see that specificity 1 wins. Hence color red is applied to the link.
Note: If both specificities are exactly the same. The one which comes last in the stylesheet wins i.e the last declaration wins.
Wrapping up
Now that you know what CSS specificity means, you might be wondering:
How does this apply in real-world development?
Very often, you're thrust into the middle of a project which has lines and lines of CSS already written by others. You try to style an element using a new selector but your style just doesn't apply. Why? Because the specificity of your selector is lower than all those other selectors!
In such cases, you can increase the specificity score of your selector using the points above or maybe use a pre-existing selector to apply that particular style. Also, using inline CSS and !important is not a recommended practice unless you have a very good reason to do so.
That's it! That's the entire lesson. Hope it decluttered many concepts in your head. Want more examples or have any doubts? Comment below!