CSS Specificity

Specificity is the set of rules browsers use to determine which CSS property values are most relevant to an element and, therefore, should be applied. Think of it as a ranking system or a "weight" assigned to different types of CSS selectors. When multiple rules target the same element and try to change the same property (like color or font-size), the browser calculates which selector has the highest specificity score to pick the winner.

Developer Tip: If you're ever confused about why a style isn't applying, open your Browser DevTools (F12). The "Styles" pane will show you which rules were overridden by crossing them out, helping you identify specificity conflicts instantly.

To understand how the browser makes these decisions, we look at the four categories of the specificity hierarchy:

  • Inline styles: These are added directly to an element’s style attribute in the HTML. They have the highest priority because they are most specific to that exact element.
  • IDs: Selectors using an ID (e.g., #header) are unique identifiers. A single ID is more powerful than any number of classes or elements combined.
  • Classes, attributes, and pseudo-classes: This category includes class selectors (.nav-item), attribute selectors ([type="text"]), and pseudo-classes like :hover or :first-child.
  • Elements and pseudo-elements: This is the lowest level of specificity. It includes standard HTML tags (h1, div, p) and pseudo-elements like ::before or ::after.
Common Mistake: Beginners often think that adding many classes to a selector will eventually override an ID. In reality, a selector with 100 classes will still lose to a single ID selector.

The specificity score is calculated as a series of four numbers (0,0,0,0). You can visualize it like a leaderboard where the left-most column is the most important:

  1. Thousands Place (1,0,0,0): Inline styles.
  2. Hundreds Place (0,1,0,0): ID selectors.
  3. Tens Place (0,0,1,0): Classes, attributes, and pseudo-classes.
  4. Ones Place (0,0,0,1): Element (tag) names and pseudo-elements.

When comparing two selectors, the browser moves from left to right. The first selector to have a higher number in a column "wins." If all numbers are equal, the Cascade takes over: the rule defined last in your CSS file is the one that gets applied.

Best Practice: Aim for low specificity by using classes (0,0,1,0) for most of your styling. This makes your CSS more modular, reusable, and easier to override when building complex layouts.

Here’s a practical example to illustrate how these scores interact in a real-world scenario:

CSS

/* Score: (0,0,0,1) - Lowest specificity */
body {
  color: blue;
}

/* Score: (0,0,1,0) - Beats the 'body' tag */
.myclass {
  color: green;
}

/* Score: (0,1,0,0) - Beats the class and the tag */
#myid {
  color: red;
}

/* Score: (0,1,1,0) - Beats the ID alone because it has an ID AND a class */
#myid.myclass {
  color: orange;
}

HTML

<!-- Inline style Score: (1,0,0,0) -->
<p id="myid" class="myclass" style="color: pink;">
  This text will be pink because inline styles win.
</p>
Watch Out: Using !important is not part of the specificity calculation, but it acts as a "nuclear option" that overrides everything else. Avoid using it unless absolutely necessary (like overriding 3rd-party library styles), as it makes debugging your CSS a nightmare.

There are a few special cases to keep in mind regarding specificity:

  • The Universal Selector (*) and combinators (like +, >, or ~) have no specificity value (0,0,0,0).
  • The :not() pseudo-class itself does not add specificity, but the selector placed inside the parentheses does. For example, div:not(.active) has the specificity of one element and one class (0,0,1,1).
  • Inheritance has no specificity. Styles inherited from a parent element (like a font family set on the body) are always overridden by direct rules applied to the child element.
Best Practice: Organize your CSS from the most general rules (top) to the most specific rules (bottom). This follows the natural flow of the cascade and makes your code more predictable.