How cascade in CSS works? this part:specificity

Following the previous article in part 1 about !important in cascade we explain how specificity affect the cascade meaning. We will use some examples to elaborate this very essential topic.

Specificity in words

Basically by specificity we mean how browsers decide to apply the most relevant CSS in the stylesheet files to an element. Therefor it depends on the matching rules which are composed by different CSS selectors.

Specificity list order

Technically we can calculate the order of applying specificity like below from highest to lowest order:

  • !important (although it is not part of specificity but it breaks the rules in CSS and has the highest order in CSS cascade anyway)
  • ID selectors (e.g., #example).
  • Class selectors (e.g., .example), attributes selectors (e.g., [type="radio"]
  • Type selectors (e.g., h1) and pseudo-elements (e.g., ::before)

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 highest specificity.

specificity rules

Never use !important as much as possible

As a rule don’t use !important unless you have no other choice. It breaks the CSS and is hard to maintain. Instead make more specific rules by mixing different cases:

<div id="test">
  <span>Text</span>
</div><br/>
div#test span { color: green; }
div span { color: blue; }
span { color: red; }

Practically the very first rule here wins. Because it is more specific. It hasa general selector targeting with an ID as the parent of the span element. Although it is first in the order but it wins. Also the second order wins over the last one as it is more specific. Order comes last.

How to override !important

As mentioned in the previous post and acording to MDN simply add another CSS rule with !important, and either give the selector a higher specificity (adding a tag, id or class to the selector), or add a CSS rule with the same selector at a later point than the existing one:

table tr td   { width: 50px !important; }
.myTable tr td { width: 50px !important; }
#myTable tr td { width: 50px !important; }

// Or add the same selector later on
tr td { width: 50px !important; }

Direct target wins over inheritance

We need to know that directly target an element is more specific over inheritance in the code:

<div>
  <article id="parent">
    <h1>Here is a title!</h1>
  </article>
</div><br/><br/>#parent {
  color: green;
}
h1 {
  color: purple;
}

The title colour will be purple and will not be inherited from its parent element.

Moreover in the same HTML if we write the below CSS:

article h1 {
  color: green;
}
div h1 {
  color: blue;
}

Although article looks closer to h1 as a direct parent but because the second rule is the last one in order it wins.

inheritance
Cascade

In addition the negation pseudo-class :not is not considered a pseudo-class in the specificity calculation. But selectors placed into the negation pseudo-class count as normal selectors when determining the count of selector types.

Also specificity is based on the form of a selector. Therefor the selector *[id="foo"] counts as an attribute selector even though it selects an ID.

We covered the most important rules of specificity here although there are minor things as well. But understanding how it works and where to use which selector is essential to write a better and more efficient CSS.

© 2019
Azadeh Faramarzi

This site is created and maintined by Azadeh Faramarzi , A passionate developer, sport and code lover who loves to share and write when she has some time.