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).
| Column | What Adds to It | Example |
|---|---|---|
| A (hundreds) | ID selectors | #header |
| B (tens) | Classes, attributes, pseudo-classes | .nav, [type], :hover |
| C (ones) | Element types and pseudo-elements | div, 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.
