CSS Specificity And Why It Matters
What is CSS Specificity
CSS specificity is the measurement of how strong a rule provided by a selector is, and determines which CSS rule is ultimately applied.
Why does it matter?
To be able to override an existing rule you need to know how to make your rule more specific (or better, equally as specific) then the rule that already exists. But making your CSS selectors more specific then then need to be, can lead to a constant fight to beat it. The use of BEM methology is an example of a way to greatly improve your management of your css's specificity by aiming to have just one level selectors.
How is it calculated?
A rules specificity is given a score (also refered to as its weight) that is calculated by breaking the rule into four catergories:
-
Inline Styles (n,0,0,0)
- Any style that is inlined on the element
-
IDs (0,n,0,0)
- The ID of an element #app
-
Classes / Attributes / Pseudo-Classes (0,0,n,0)
- Any class names .red, attribute [type=text] or pseudo-classes :hover
-
Elements / Pseudo Elements (0,0,0,n)
- Any elements div, or pseudo elements :after
The specificity is then calculated by counting how many are in each category, then concatenating the values in the order stated above, i.e
<style>
#app div.amazing.red {
color: red;
}
#app header div.amazing {
color: green;
}
</style>
<div id="app">
<header>
<div class="amazing red">Am i red or green?</div>
</header>
</div>
In this example #app div.amazing.red
has a score of 0121
, calculated like so:
0 - Inline Styles
1 - ID
2 - Classes
1 - Element
Which wins over #app header div.amazing
as it has a score of 0112
, calculated like so:
0 - Inline Styles
1 - ID
1 - Class
2 - Elements
Other Rules
Rules with selectors of the same specificity
If a rule has selectors with the same specificity of an existing rule, the rule that came last is applied, this is the most ideal situation so you are not constantly increasing specificity with each rule.
!important is BAD
A rule with !important
wins over everything, even inline style. Awesome! you might think, then i don't have to worry about specificity, as your nice new rule will be applied. True... but then when it comes to override that rule, the only way to override that is to make another !important
rule after the previous !important
rule, and the terrible cycle begins.
- Always look for a way to use specificity before even considering
!important
- Only use
!important
on page-specific CSS that overrides foreign CSS. - Never use
!important
when you're writing a component. - Never use
!important
on site-wide CSS.
Bottom line is you should never use !important
unless you have to override an existing !important
, but if you are never using !important
in the first place you should never need to do this!
:not() exception
The :not() pseudo-class has no specificity value, but selectors placed into the :not() pseudo-class count as normal selectors when determining the count of selector types
Universal selector and combinators
Universal selector (*
) and combinators (+
, >
, ~
, '') have no specificity value.
Inheritance and User-Agent styles
Rules inherited from parent elements, and default user agent styles have no specificity score.
Bonus Image (Cheat-Sheet)
Front-End > 2018/02/08 > CSS Specificity And Why It Matters > css-specificity-wars.png