Understanding CSS Specificity: How Styles Are Applied and Overridden

Understanding CSS Specificity: How Styles Are Applied and Overridden

Cascading Style Sheets (CSS) is the backbone of web design, allowing developers to style their web pages in an organized and efficient manner. However, when working with CSS, many developers encounter a common issue: why is one style being applied over another? This is where CSS specificity comes into play. 

Specificity is a fundamental concept that dictates which CSS rules take precedence when multiple styles are applied to the same element. In this article, I'll dive into the mechanics of CSS specificity, how styles are applied, and the ways to override conflicting styles for optimal design control.

What Is CSS Specificity?

At its core, CSS specificity is a set of rules that determine which styles are applied to an element when multiple rules could potentially match. CSS styles "cascade" down from the most general rules to the most specific ones. If two or more rules target the same element, specificity rules help CSS decide which rule to prioritize.

To understand this better, consider specificity as a form of weight assigned to different CSS selectors. The selector with the higher specificity value will "win" and have its styles applied.

For the most part, most developers learn quickly what the primary rules are. However, there are a few edge scenarios that most miss, and hopefully this article will shed some light on those.

Types of selectors

CSS specificity is calculated based on the types of selectors used. Selectors can be classified into four main categories, and each category carries a different weight to it:

1. Inline Styles: These are styles written directly in the HTML element, using the style attribute. They have the highest specificity, however, are typically not recommended as they can clutter up the markup and make it difficult to manage long term.

<p style="color: blue;">This text is blue.</p>

2. ID Selectors: These are styles targeting a specific element by its ID. ID selectors are very powerful and have a high specificity.

#main-content {
  color: red;
}

3. Class, Attribute, and Pseudo-Class Selectors: These selectors target classes, attributes, or elements in specific states (like :hover). They have moderate specificity.

.highlight {
  color: green;
}

4. Type (Element) and Pseudo-Element Selectors: These are the most basic selectors, targeting elements like p, h1, or div. They have the lowest specificity.

p {
  color: black;
}

CSS specificity scores

Lucky for developers that there is actual math behind the scenes, so you don't have to guess or make assumptions about why a specific element takes on certain rules.

Each selector is assigned a specificity score based on how it matches elements. Here's how it works, broken down by the four categories:

Inline Styles: Score = 1,000

ID Selectors: Score = 100

Class, Attribute, and Pseudo-Class Selectors: Score = 10

Element and Pseudo-Element Selectors: Score = 1

The specificity score of a rule is calculated by adding the values for each type of selector present in that rule. For example:

div p.highlight {
  color: blue;
}

div (type selector) = 1

p (type selector) = 1

.highlight (class selector) = 10

So, the total specificity score is 12 for that particular rule.

Now, compare that with the following:

#main p {
  color: red;
}

#main (ID selector) = 100

p (type selector) = 1

The total specificity score for this rule is 101, meaning it will take precedence over the previous rule.

Cascading rules

CSS is short for "Cascading Style Sheets," meaning that stylesheets follow a cascade of rules. If multiple rules with the same specificity target an element, the last declared rule in the stylesheet will be applied.

For example:

p {
  color: green;
}

p {
  color: blue;
}

In this case, the paragraph will be blue, as the second rule was declared later, despite both having the same specificity score.

Common pitfalls

Specificity can be tricky, especially when working with complex stylesheets. Here are some common problems developers face:

Overly specific selectors: Using too many ID or class selectors can lead to unmanageably high specificity, making it hard to override styles later on.

Conflicting styles: When multiple styles target the same element with similar specificity, it can be difficult to predict which will be applied.

!important rule overuse: Developers sometimes use !important to forcefully override other styles, but overusing it can make debugging CSS much harder, particularly if your CSS is broken up into multiple files.

How to override styles in CSS

Knowing how to override styles is crucial for fine-tuning your web design. Here are some tips for doing so effectively:

1. Increase specificity: By making your selector more specific, you can override other rules. For example, to override a class selector, use an ID selector instead or add another class selector.

2. Use !important sparingly: The !important rule forces a style to be applied regardless of specificity. While this can be useful in some cases, overuse can lead to convoluted code. Try to reserve it for special cases where increasing specificity isn’t an option.

.override {
  color: red !important;
}

3. Organize styles logically: Structure your CSS so that general styles are applied first, followed by more specific rules. This makes it easier to understand and manage specificity conflicts.

4. Leverage inheritance: Many CSS properties are inherited by child elements. Rather than adding extra selectors, take advantage of inheritance to apply consistent styles across elements.

5. Apply CSS variables: CSS custom properties (variables) can also help manage large-scale overrides by centralizing style definitions.

Example

Let’s look at some real-world examples of specificity in action.

Basic Example:

.button {
  background-color: blue;
}

#submit-button {
  background-color: red;
}

In this case, the button with ID submit-button will be red because the ID selector has a higher specificity than the class selector.

Combining Selectors:

a {
  color: green;
}

a:hover {
  color: purple;
}

Here, when a user hovers over a link, the color changes to purple. The pseudo-class :hover has a specificity score of 10, which is higher than the type selector a (which has a score of 1).

CSS specificity best practices

To avoid specificity issues and keep your stylesheets clean, follow these best practices:

Use classes for styling: Avoid using IDs for styling, as they have very high specificity and can be hard to override.

 Be consistent: Stick to a consistent naming convention for your selectors to avoid unnecessary complexity. 

Avoid deep nesting: The deeper your selector chain, the higher the specificity. Aim for flatter, more maintainable selectors.

Limit !important: Only use it when absolutely necessary, and try to resolve conflicts through specificity instead.

Conclusion

Understanding CSS specificity is essential for mastering CSS. It not only helps you troubleshoot conflicting styles but also ensures your design scales smoothly as your project grows. By following best practices like avoiding overly specific selectors, organizing your styles logically, and knowing when to override styles, you can create clean, efficient, and maintainable stylesheets.

Walter G. author of blog post
Walter Guevara is a Computer Scientist, software engineer, startup founder and previous mentor for a coding bootcamp. He has been creating software for the past 20 years.

Get the latest programming news directly in your inbox!

Have a question on this article?

You can leave me a question on this particular article (or any other really).

Ask a question

Community Comments

No comments posted yet

Add a comment