According to how CSS works, browsers determine which CSS declarations win over the others by cascading in following descending order of priority:
!important
annotation. The precedence of the various origins is, in descending order:1. Transition
2. User agent + `!important`
3. User + `!important`
4. Author + `!important`
5. Animation
6. Author
7. User
8. User agent
Specificity is needed when there’s still conflict after comparing origin and importance. When multiple declarations have equal specificity, the last declaration found in the CSS is applied to the element.
Inheritance is part of defaulting which happens after cascading, so styles for a directly targeted element will always take precedence over inherited styles, regardless of the specificity of the inherited rule.
The resulting specificity is not a number but a tuple of numbers like (a,b,c)
. Specificity tuples are compared by comparing corresponding elements of two tuples using following algorithm:
(1,0,0,0,0)
vs (1,1,1)
=> (1,0,0,0,0)
vs (0,0,1,1,1)
(1,0,0,0,0) > (1,0,0,0)
(1,0,0,0) > (1,3,3)
(1,0,0) > (0,1,0)
(0,12,1) > (0,1,0)
(0,0,2) > (0,0,1)
The !important
value appended a CSS property value is an automatic win with specificity of (1,0,0,0,0)
. It overrides even inline styles from the markup. The only way an !important
value can be overridden is with another !important
rule declared later in the CSS and with equal or great specificity value otherwise.
Using !important
considers a bad practice and should be avoided because it makes debugging more difficult by breaking the natural cascading in your stylesheets.
Inline styles added to an element (e.g., style=“font-weight: bold;” ) always overwrite any styles in external stylesheets, and thus can be thought of as having the specificity (1,0,0,0)
.
Both inline styles and !important
are considered very bad practice, but sometimes you need the latter to override the former.
:not(x)
are counted like any other, but the negation itself does not count as a pseudo-class.*
), combinators (+, >, ~, ' ', ||
) have no effect on specificity.* /* a=0 b=0 c=0 -> specificity = (0,0,0) */
li /* a=0 b=0 c=1 -> specificity = (0,0,1) */
ul li /* a=0 b=0 c=2 -> specificity = (0,0,2) */
ul ol+li /* a=0 b=0 c=3 -> specificity = (0,0,3) */
h1 + *[rel=up] /* a=0 b=1 c=1 -> specificity = (0,1,1) */
ul ol li.red /* a=0 b=1 c=3 -> specificity = (0,1,3) */
li.red.level /* a=0 b=2 c=1 -> specificity = (0,2,1) */
#x34y /* a=1 b=0 c=0 -> specificity = (1,0,0) */
#s12:not(foo) /* a=1 b=0 c=1 -> specificity = (1,0,1) */