CSS Specificity and How to Overwrite It

Specificity is important in determining which CSS declarations will take precedence over others. This article was created to help you understand how specificity works so you can write clean, easy to read, and follow CSS code.

What is Specificity?

Specificity is a weight applied to CSS declarations that determines the most relevant CSS property values within a given element and is based on matching rules composed of different CSS selectors.

The importance of each CSS declaration is determined by the following hierarchy of selector types:

  • Type selectors: (e.g., div) and pseudo-elements (e.g., :before)
  • Class selectors: Classes (e.g., .my-class), attribute selectors (e.g., [type="input"]), and pseudo-classes (e.g., :active)
  • ID selectors: (e.g. #my-item)

This hierarchy is used in determining which CSS declarations to use and how to use them. In cases where multiple declarations have equal specificity, the last declaration found in the CSS is applied to the specified element. For example, if the same type selector was declared twice with multiple styling rules:

<style>
div#text {
color: red;
}

div#text {
color: blue;
}
</style>

<div id="text">My text container.</div>

The div container with ID "text" will use the latter rule since the type selector is declared twice, giving each of them equal specificity. If we were to swap the declarations (move blue below red), then the color of the text color in the div container would then become red since it would now become the latter declaration.

More Specific Selectors Have Greater Specificity

Here's another example of how the specificity hierarchy works. This code snippet shows another red/blue example within a div selector. The difference in this example is the first declaration contains a specified ID name, while the second declaration only contains the selector type:

<style>
div#text {
color: red;
}

div {
color: blue;
}
</style>

<div id="text">The text color is red.</div>

Since the first declaration, div#text, contains a more specific specificity by declaring the selector's ID, it gains precedence instead of using the latter rule without the more specific declaration. Therefore, the text becomes red instead of blue.

How to Overwrite CSS Declarations

You can overwrite any existing CSS declarations by using the !important rule. This rule was introduced back in CSS1 and, while it can be handy to use in some cases, it's generally best practice to stay away from it unless absolutely necessary.

Let's use the same example from above, but with the !important rule added:

<style>
div#text {
color: red !important;
}

div#text {
color: blue;
}
</style>

<div id="text">My text container.</div>

In the first example, the div container with ID "text" contained blue text. This was because even though the same selector was declared twice, the latter declaration was used by following the rules of specificity.

However, in this example, we've added the !important rule to the first div#text declaration block. Since !important overwrites the specifity rules, the text color now becomes red instead of blue.

If you're going to use the !important rule for CSS declaration overwriting, use it sparingly. It's best to consider specificity and CSS organization first, as that's how CSS styling is designed. It also helps keep your code much cleaner.

A great example of where you could use the !important rule is in cases where your custom styling has already been used by another selector declaration from a third-party script or plugin you've included in your project. You generally wouldn't want to alter those scripts or plugins directly. You could just overwrite rules using the !important rule in your own custom CSS code.

Other Important Tidbits

A few other pieces of information regarding specificity that are helpful:

  • Directly targeted elements will always take precedence over CSS rules where an element inherits rules from its parent element.
  • Universal selectors *, combinators +, ~, etc., and negation pseudo-classes :not(), have no effect on specificity.
  • In addition to the previous rule, note that selectors declared inside :not() pseudo-classes actually do take precedence.

Conclusion

Specificity can be a hard concept to wrap your head around at first. Over time, you'll become more knowledgeable of it as you practice on your own or using real-world examples.