← Back to blog
Why CSS Specificity Works the Way It Does

Why CSS Specificity Works the Way It Does

#css#internals#deepdive

Why CSS Specificity Works the Way It Does

CSS specificity is one of those concepts that most developers take for granted, but it's actually a fascinating topic to explore deeply. In this article, we'll dive into the deeper mechanics behind CSS specificity and explain why it works the way it does. We'll also provide code examples that reveal the truth about how specificity is calculated and why it matters in practice.

The Surface-Level Understanding

At a high level, CSS specificity refers to the priority given to different selectors when applying styles. The more specific a selector is, the higher its priority will be. There are four types of selectors that contribute to an element's specificity:

  1. Type selectors (e.g., h1, p)
  2. Class selectors (e.g., .header, .footer)
  3. ID selectors (e.g., #nav, #content)
  4. Attribute selectors (e.g., [href], [src="img.jpg"])

The specificity of a selector is determined by the number and type of each selector in the chain. For example, a selector with two class selectors has a higher specificity than one with only one class selector. The following table illustrates this concept:

| Selector Chain | Specificity Score | | -------------- | ----------------- | | h1 | 1 | | .header | 10 | | #nav | 100 | | [href] | 1,000 | | .footer.nav | 21 | | p#content | 11 |

The specificity of a selector is used to determine which style will be applied when there are conflicts. When multiple selectors target the same element, the one with the highest specificity wins.

The Deeper Reality

But what happens behind the scenes when CSS specificity is calculated? Let's dive into the details and explore how it works in practice.

CSS specificity is determined by a calculation called "specificity arithmetic." This algorithm takes into account the number of each type of selector in a chain, as well as their position within the chain. Here's a simplified example:

Let's say we have two selectors, one with 2 class selectors and another with 1 class selector. The specificity score for each selector would be calculated as follows:

| Selector Chain | Specificity Score | | ----------------- | --------------------- | | .header .footer | 4 (2 class selectors) | | .nav | 3 (1 class selector) |

The algorithm works by counting the number of each type of selector in the chain and multiplying them together. For example, a selector with 2 class selectors would have a score of 2 x 2 = 4. The final specificity score is determined by adding up all the scores for each selector in the chain.

Now that we know how to calculate specificity, let's talk about why it matters in practice. When multiple selectors target the same element, the one with the highest specificity wins. This means that if you have two conflicting styles, the one with the higher specificity will be applied.

Here's an example:

.header {
  font-size: 24px;
}

h1 {
  font-size: 36px;
}

<h1 class="header">Header</h1>

In this case, the font-size style from .header will be applied to the <h1> element because it has a higher specificity score than the h1 selector. This can be useful when you want to override default styles or create more complex selectors.

Code Examples That Reveal the Truth

Here are some code examples that demonstrate how CSS specificity works in practice:

// Example 1: Conflicting styles with same specificity
.header {
  font-size: 24px;
}

h1 {
  font-size: 36px;
}

<h1 class="header">Header</h1>

In this example, both .header and h1 have the same specificity score, so the font-size style from whichever selector is applied last will win. In this case, it's the font-size: 36px from h1.

// Example 2: Nested selectors with higher specificity
.nav {
  font-size: 18px;
}

#content .header {
  font-size: 24px;
}

<div id="content">
  <h1 class="header">Header</h1>
  <p>Paragraph</p>
</div>

In this example, the font-size style from .nav will not be applied to the <h1> element because it has a lower specificity score than #content .header. The font-size: 24px style from #content .header is applied instead. This is because the .header selector in this chain has a higher specificity than the .nav selector, even though they have the same number of class selectors.

// Example 3: Selector types and positions
.footer h1 {
  font-size: 24px;
}

#content p {
  font-size: 18px;
}

<div id="content">
  <h1>Heading</h1>
  <p>Paragraph</p>
</div>

In this example, the font-size style from .footer h1 will not be applied to the <h1> element because it has a lower specificity score than #content p. The font-size: 18px style from #content p is applied instead. This is because the selector types (element and class) in this chain have different weights, with element selectors having more weight than class selectors.

Why This Matters in Practice

Understanding CSS specificity can help prevent bugs and improve performance. Here are a few reasons why:

  1. Preventing conflicts: By understanding how specificity works, you can avoid conflicting styles from different sources. This is especially important when working with third-party libraries or frameworks that may have conflicting styles.
  2. Optimizing selectors: Specificity can help you optimize your CSS code by reducing the number of selectors and increasing efficiency. For example, instead of using multiple class selectors to target an element, you could use a single ID selector instead.
  3. Improving maintainability: Understanding specificity can also improve the maintainability of your codebase. When you know which styles are applied based on their specificity score, it's easier to understand and modify existing styles without breaking anything else.

The Key Insight

The key insight into CSS specificity is that it's a calculation-based system that prioritizes more specific selectors over less specific ones. This means that if you have conflicting styles, the one with the higher specificity score will be applied. By understanding how this works, you can write cleaner, more efficient CSS code that is easier to maintain and debug.