CSS Specificity

CSS specificity decides which style rule wins when two or more rules target the same element. Every CSS selector earns a score, and the highest score wins. Understanding specificity stops you from fighting your own styles and writing unnecessary !important overrides.

A Real-World Analogy

DIAGRAM — The Job Interview:

Hiring for one position. Three candidates apply.

Candidate A: General degree          → Score: 10
Candidate B: Specific degree + cert  → Score: 100
Candidate C: Same as B + top school  → Score: 110

Candidate C gets the job.

CSS works the same way.
A more specific selector always wins — regardless of order.

The Specificity Score System

Think of the score as a three-column number: (A, B, C).

ColumnWhat Adds to ItExample
A (hundreds)ID selectors#header
B (tens)Classes, attributes, pseudo-classes.nav, [type], :hover
C (ones)Element types and pseudo-elementsdiv, p, ::before
DIAGRAM — Specificity Score Table:

Selector             │  A  │  B  │  C  │ Total
─────────────────────┼─────┼─────┼─────┼───────
p                    │  0  │  0  │  1  │  001
.intro               │  0  │  1  │  0  │  010
p.intro              │  0  │  1  │  1  │  011
#main                │  1  │  0  │  0  │  100
#main p              │  1  │  0  │  1  │  101
#main .intro p       │  1  │  1  │  1  │  111

The selector with the higher total score wins. Columns are compared left to right, just like comparing numbers: (1,0,0) beats (0,9,9) because the A column wins immediately.

Specificity in Action

Example 1: Class vs Element

<p class="intro">Welcome to CSS!</p>

p {
  color: black; /* specificity: 001 */
}

.intro {
  color: blue;  /* specificity: 010 — wins */
}

The text turns blue because .intro scores higher than p.

Example 2: ID Always Beats Class

<p id="title" class="intro">Hello!</p>

.intro {
  color: blue;   /* specificity: 010 */
}

#title {
  color: red;    /* specificity: 100 — wins */
}

The text turns red. An ID selector always beats any class, no matter how many classes you combine.

Example 3: Multiple Classes vs One ID

.nav.active.highlight {
  color: green;  /* specificity: 030 */
}

#nav {
  color: orange; /* specificity: 100 — still wins */
}

Even three classes stacked together (030) cannot beat a single ID (100).

Inline Styles Beat Everything

Inline styles — CSS written directly on the HTML element — sit above all external stylesheet rules. They have an implied score of (1,0,0,0), which beats any selector.

<p style="color: purple;">This text is purple no matter what.</p>

/* This rule won't work: */
#myId .myClass p {
  color: green; /* loses to the inline style */
}

The !important Override

!important forces a declaration to win above all other rules, including inline styles. It breaks the normal specificity flow.

p {
  color: black !important; /* forces black, ignores all other rules */
}

#title {
  color: red; /* loses, even though #title has higher specificity */
}

When to use it: Rarely. Use !important only when you cannot control third-party CSS (like a plugin's styles). Overusing it makes your stylesheet hard to debug.

The Universal Selector Has Zero Specificity

The * selector and combinators like >, +, ~, and a space do not add any specificity score.

* {
  box-sizing: border-box; /* specificity: 000 */
}

div p {
  margin: 0;  /* specificity: 002 — two elements */
}

The :is(), :not(), :has() Pseudo-Classes

These functional pseudo-classes take the specificity of their most specific argument.

:is(#header, p) {
  color: blue;
  /* specificity = 100 (because #header is the most specific argument) */
}

Full Specificity Ladder (Lowest to Highest)

DIAGRAM — Specificity Pyramid:

        ▲ Highest
        │
        │   !important
        │   ──────────────────────────────
        │   Inline styles    (1,0,0,0)
        │   ──────────────────────────────
        │   ID selectors     (0,1,0,0)
        │   ──────────────────────────────
        │   Classes, attributes, pseudo-classes  (0,0,1,0)
        │   ──────────────────────────────
        │   Elements, pseudo-elements    (0,0,0,1)
        │   ──────────────────────────────
        │   Universal selector *         (0,0,0,0)
        ▼ Lowest

Order of Appearance as a Tiebreaker

When two selectors have the exact same specificity score, the one that appears last in the stylesheet wins.

p { color: red; }
p { color: blue; } /* Same specificity — this one wins because it's last */

Practical Tips

  • Write selectors with the lowest specificity needed. This keeps styles easy to override later.
  • Avoid IDs in your CSS. Use classes instead — they score lower and are reusable.
  • Never chain IDs like #parent #child. The score jumps too high.
  • If a style isn't applying, open the browser DevTools and check the computed styles panel. It shows which rule wins and why.
  • Add more specificity by adding a class, not by adding !important.

DevTools Tip

In Chrome or Firefox, right-click any element and choose "Inspect." The Styles panel shows all rules applied to that element. Overridden rules appear with a strikethrough, making it easy to see which rule won and what score it carries.

Mastering specificity means you write CSS that does exactly what you expect, instead of adding override after override and wondering why nothing works.

Leave a Comment

Your email address will not be published. Required fields are marked *