Calculating Selector Specificity

suggest change

Each individual CSS Selector has its own specificity value. Every selector in a sequence increases the sequence’s overall specificity. Selectors fall into one of three different specificity groups: A, B and c. When multiple selector sequences select a given element, the browser uses the styles applied by the sequence with the highest overall specificity.

Group | Comprised of | Examples | —— | –––––––––––––––––––– | ––––– |A | id selectors | #foo |B | class selectors attribute selectors pseudo-classes | .bar [title], [colspan="2"] :hover, :nth-child(2) |c | type selectors pseudo-elements | div, li ::before, ::first-letter |

Group A is the most specific, followed by Group B, then finally Group c.

The universal selector (\*) and combinators (like \> and ~) have no specificity.

Example 1: Specificity of various selector sequences

#foo #baz {}      /* a=2, b=0, c=0 */

#foo.bar {}       /* a=1, b=1, c=0 */

#foo {}           /* a=1, b=0, c=0 */

.bar:hover {}     /* a=0, b=2, c=0 */

div.bar {}        /* a=0, b=1, c=1 */

:hover {}         /* a=0, b=1, c=0 */

[title] {}        /* a=0, b=1, c=0 */

.bar {}           /* a=0, b=1, c=0 */

div ul + li {}    /* a=0, b=0, c=3 */

p::after {}       /* a=0, b=0, c=2 */

*::before {}      /* a=0, b=0, c=1 */

::before {}       /* a=0, b=0, c=1 */

div {}            /* a=0, b=0, c=1 */

* {}              /* a=0, b=0, c=0 */

Example 2: How specificity is used by the browser

Imagine the following CSS implementation:

#foo {
  color: blue;
}

.bar {
  color: red;
  background: black;
}

Here we have an ID selector which declares color as blue, and a class selector which declares color as red and background as black.

An element with an ID of #foo and a class of .bar will be selected by both declarations. ID selectors have a Group A specificity and class selectors have a Group B specificity. An ID selector outweighs any number of class selectors. Because of this, color:blue; from the #foo selector and the background:black; from the .bar selector will be applied to the element. The higher specificity of the ID selector will cause the browser to ignore the .bar selector’s color declaration.

Now imagine a different CSS implementation:

.bar {
  color: red;
  background: black;
}

.baz {
  background: white;
}

Here we have two class selectors; one of which declares color as red and background as black, and the other declares background as white.

An element with both the .bar and .baz classes will be affected by both of these declarations, however the problem we have now is that both .bar and .baz have an identical Group B specificity. The cascading nature of CSS resolves this for us: as .baz is defined after .bar, our element ends up with the red color from .bar but the white background from .baz.

Example 3: How to manipulate specificity

The last snippet from Example 2 above can be manipulated to ensure our .bar class selector’s color declaration is used instead of that of the .baz class selector.

.bar {}        /* a=0, b=1, c=0 */
.baz {}        /* a=0, b=1, c=0 */

The most common way to achieve this would be to find out what other selectors can be applied to the .bar selector sequence. For example, if the .bar class was only ever applied to span elements, we could modify the .bar selector to span.bar. This would give it a new Group C specificity, which would override the .baz selector’s lack thereof:

span.bar {}    /* a=0, b=1, c=1 */
.baz {}        /* a=0, b=1, c=0 */

However it may not always possible to find another common selector which is shared between any element which uses the .bar class. Because of this, CSS allows us to duplicate selectors to increase specificity. Instead of just .bar, we can use .bar.bar instead (See The grammar of Selectors, W3C Recommendation). This still selects any element with a class of .bar, but now has double the Group B specificity:

.bar.bar {}    /* a=0, b=2, c=0 */
.baz {}        /* a=0, b=1, c=0 */

!important and inline style declarations

The !important flag on a style declaration and styles declared by the HTML style attribute are considered to have a greater specificity than any selector. If these exist, the style declaration they affect will overrule other declarations regardless of their specificity. That is, unless you have more than one declaration that contains an !important flag for the same property that apply to the same element. Then, normal specificity rules will apply to those properties in reference to each other.

Because they completely override specificity, the use of !important is frowned upon in most use cases. One should use it as little as possible. To keep CSS code efficient and maintainable in the long run, it’s almost always better to increase the specificity of the surrounding selector than to use !important.

One of those rare exceptions where !important is not frowned upon, is when implementing generic helper classes like a .hidden or .background-yellow class that are supposed to always override one or more properties wherever they are encountered. And even then, you need to know what you’re doing. The last thing you want, when writing maintainable CSS, is to have !important flags throughout your CSS.

A final note

A common misconception about CSS specificity is that the Group A, B and c values should be combined with each other (a=1, b=5, c=1 => 151). This is not the case. If this were the case, having 20 of a Group B or c selector would be enough to override a single Group A or B selector respectively. The three groups should be regarded as individual levels of specificity. Specificity cannot be represented by a single value.

When creating your CSS style sheet, you should maintain the lowest specificity as possible. If you need to make the specificity a little higher to overwrite another method, make it higher but as low as possible to make it higher. You shouldn’t need to have a selector like this:

body.page header.container nav div#main-nav li a {}

This makes future changes harder and pollutes that css page.


You can calculate the specificity of your selector here

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents