Understanding CSS Selector Priority/Specificity

Understanding CSS selector priority / specificity

I'll just toss in a link to the CSS 2.1 spec itself, and how browsers are supposed to calculate specificity:

CSS 2.1 Section 6.4.3:

A selector's specificity is calculated as follows:

  • count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
  • count the number of ID attributes in the selector (= b)
  • count the number of other attributes and pseudo-classes in the selector (= c)
  • count the number of element names and pseudo-elements in the selector (= d)
  • The specificity is based only on the form of the selector. In particular, a selector of the form "[id=p33]" is counted as an attribute selector (a=0, b=0, c=1, d=0), even if the id attribute is defined as an "ID" in the source document's DTD.

Concatenating the four numbers a-b-c-d (in a number system with a large base) gives the specificity.

If the specificities are equal, then CSS 2.1 Section 6.4.1 comes into play:


  1. Finally, sort by order specified: if two declarations have the same weight, origin and specificity, the latter specified wins. Declarations in imported style sheets are considered to be before any declarations in the style sheet itself.

Note that this is talking about when the style is defined, not when it is used. If classes .a and .b have equal specificity, whichever is defined last in the stylesheet(s) wins. <p class="a b">...</p> and <p class="b a">...</p> will be styled identically, based on the definition order of .a and .b.

What are the priorities among CSS selectors

The gory details in the spec are actually reasonably readable. In summary:

  1. !important rules and inline style rules win most.

  2. Otherwise, normally the more specific wins. #id is a more specific selector than .classname is a more specific selector than tagname.

  3. Where rules are equally specific, the one declared last wins.

There is no particular reason why this ‘shouldn't happen’. It's normal to specify a broad-brush rule and then add a more specific rule to target one case; multiple same-property rules on a single element are not unusual or undesirable.

Understanding specificity: achieving desired selector outcomes without using !important

A class has a specificity of 10. An element has a specificity of 1.

Therefore, in the first instance:

  • the .main li a selector has a specificity of 12.
  • the .active a selector has a specificity of 11

Because they both target the same element, and the former has a higher specificity, the latter loses the battle to style the element.

In the second instance:

  • the .primary p selector has a specificity of 11.
  • the .copyright selector has a specificity of 10.

Again, because they both target the same element, and the former has a higher specificity, the latter loses the battle to style the element.

The !important annotation trumps all specificity. Hence, with that applied, .active a and .copyright re-take the elements.

If you want to remove !important, which would be the right thing to do as it's not necessary here, you can instead boost the specificity of the selectors.

An ID has a specificity of 100. So that can quickly move a selector up in priority.

Here are some examples:

.main li a      { color: #7ab2c1; }  /* previous winner; specificity 12 */.main .active a { color: #ff0000; }  /* added class selector; specificity now 21 */.primary p      { font-size: 12px; } /* previous winner; specificity 11 */#copyright      { font-size: 8px;} /* switched to ID selector; specificity now 100 */
<nav class="main">  <ul class="group">    <li class="active"><a href="#">Home</a></li>    <li><a href="#">About</a></li>    <li><a href="#">Contact</a></li>  </ul></nav><footer class="primary">  <p><a href="#">Sign up</a> for our newsletter, it's a racket!</p>  <p id="copyright">Copyright © Sven's Snowshoe Emporium.                    All Rights Reserved.</p></footer>

Why do I have to use the !important in this case?

Be more specific with your css and remove all your !importants:

.parent div.child {
width: 50%;
height: 50px;
}

should work just fine

Am I correct in my understanding of selectors?

It's because classes have higher specificity value than Elements and Pseudo Elements. In your case .top-menu have higher specificity than the element ul, therefore its style is followed/used. Refer to this table for specificity:

Specificity Reference

More on specificity here.

Specificity order of CSS tag selectors with equal specificity

Specificity matters when two or more selectors are matching the same element – not the case here.

e.g.:
in the example below the more specific selector div#id.class won't win against h1 because they are referring to two distinct elements, so the color of h1 is determined by the first rule

h1{    color: blue;}
div#id.class { color: red;}
<html><head></head><body>    <div id="id" class="class">        <h1>This is the title</h1>    </div></body></html>

Which of the following two selectors has a higher CSS specificity?

You can't hover over a ::first-letter, however, all things being equal, the first selector is stronger:

/* Selector 1 -> #object h2::first-letter */#this h2::first-letter{   color: red}
/* Selector 2 -> body .item div h2::first-letter:hover */body .item div h2::first-letter{ color: blue;}
<div class="item">  <div id="this">    <h2>This is a title</h2>  </div></div>

What is the order of precedence for CSS?

There are several rules ( applied in this order ) :

  1. inline css ( html style attribute ) overrides css rules in style tag and css file
  2. a more specific selector takes precedence over a less specific one
  3. rules that appear later in the code override earlier rules if both have the same specificity.
  4. A css rule with !important always takes precedence.

In your case its rule 3 that applies.

Specificity for single selectors from highest to lowest:

  • ids (example: #main selects <div id="main">)
  • classes (ex.: .myclass), attribute selectors (ex.: [href=^https:]) and pseudo-classes (ex.: :hover)
  • elements (ex.: div) and pseudo-elements (ex.: ::before)

To compare the specificity of two combined selectors, compare the number of occurences of single selectors of each of the specificity groups above.

Example: compare #nav ul li a:hover to #nav ul li.active a::after

  • count the number of id selectors: there is one for each (#nav)
  • count the number of class selectors: there is one for each (:hover and .active)
  • count the number of element selectors: there are 3 (ul li a) for the first and 4 for the second (ul li a ::after), thus the second combined selector is more specific.

A good article about css selector specificity.



Related Topics



Leave a reply



Submit