How to Increase CSS Class Selector Specificity to Beat the ID Selector Without Using Important

Recently, while working on some legacy code, I had to figure out how to overwrite ID selector styles without using !important.

The CSS was similar to this

<div id="parent">
  <div class="child">Content</div>
</div>

<style>
  /* specificity 100 + 10 = 110 */
  #parent .child {
    color: red;
  }

  /* specificity 10 */
  .child {
    color: yellow;
  }
</style>

This results in a text with red color, but in my case, I needed to make the text yellow.

Normally, I would just refactor the CSS and HTML, but in this case, I couldn’t change the HTML and order of CSS due to some legacy code.

The easy solution would be to use an infamous !important keyword to overwrite everything, but I didn’t want to go that way.

Using attribute selector

The better way is to change the ID selector to the attribute selector. Instead of #parent it's possible to use [id="parent"]. This has the same specificity as a class selector.

Now instead of specificity 110, it is down to 20.

/* specificity 10 + 10 = 20 */
[id="parent"] .child {
  color: red;
}

/* specificity 10 */
.child {
  color: yellow;
}

Chaining the selector with itself

Now I had to increase the .child specificity above 20 to beat the [id="parent" .child" selector. One way to achieve that is to chain the class selector with itself.

The specificity of .child is 10. The specificity of .child.child.child is 30.

<div id="parent">
  <div class="child">Content</div>
</div>

<style>
  /* specificity 10 + 10 = 20 */
  [id="parent"] .child {
    color: red;
  }

  /* specificity 10 + 10 + 10 = 30 */
  .child.child.child {
    color: yellow;
  }
</style>

This is an easy way to bump up specificity without adding additional classes or knowing about the context where the item will be placed.

I find this better than using !important, but it is still a hack. If possible, try to avoid this.