Ad – 728×90
🔧 Advanced CSS

CSS Specificity – Why Your Styles Get Overridden

Specificity is the algorithm browsers use to decide which CSS rule wins when multiple rules target the same element and property. Understanding it means you stop fighting your own styles — and you know exactly why color: red isn't working and what to do about it. Specificity is one of the most common sources of confusion in CSS, and mastering it will make you dramatically faster at debugging.

⏱️ 20 min read 🎯 Intermediate 📅 Updated 2026 👁️ Lesson 4 of 5

How Specificity Works

Each CSS selector has a specificity score — a three-column value written as (a, b, c). The browser compares scores column by column, left to right. The rule with the highest score wins. If scores are equal, the rule declared last in the source wins (the cascade).

Category What counts Score contribution
Column A — ID selectors #id (1, 0, 0)
Column B — Class, attribute, pseudo-class .class, [attr], :hover, :nth-child() (0, 1, 0)
Column C — Element, pseudo-element div, p, a, ::before (0, 0, 1)
Inline style style="..." attribute (1, 0, 0, 0)
Universal / combinators *, >, +, ~,   (0, 0, 0)
CSS – Calculating specificity scores
/* Selector                         Score (a, b, c) */

p                                /* (0, 0, 1) — 1 element */
.intro                           /* (0, 1, 0) — 1 class */
#header                          /* (1, 0, 0) — 1 ID */
div p                            /* (0, 0, 2) — 2 elements */
.nav li                          /* (0, 1, 1) — 1 class, 1 element */
.nav li a                        /* (0, 1, 2) — 1 class, 2 elements */
#header .nav li a                /* (1, 1, 2) — 1 ID, 1 class, 2 elements */
.card:hover                      /* (0, 2, 0) — 1 class, 1 pseudo-class */
input[type="text"]               /* (0, 1, 1) — 1 attribute, 1 element */
ul li:first-child                /* (0, 1, 2) — 1 pseudo-class, 2 elements */
#nav > ul > li > a:hover         /* (1, 1, 3) — 1 ID, 1 pseudo-class, 3 elements */

Comparing Specificity

CSS – Specificity comparison examples
/* Which color wins? */
p { color: blue; }           /* (0,0,1) */
.text { color: red; }        /* (0,1,0) */
/* Winner: .text → red (0,1,0 beats 0,0,1) */

#main p { color: green; }    /* (1,0,1) */
.section .text { color: orange; } /* (0,2,0) */
/* Winner: #main p → green (1 in column A wins regardless of B and C) */

/* Same specificity — last one in source wins */
.btn { background: blue; }   /* (0,1,0) */
.cta { background: red; }    /* (0,1,0) */
/* 
Ad – 336×280

!important

!important overrides all specificity — including inline styles. It adds a separate "important" layer above the normal specificity scale. When two !important declarations compete, the one with higher specificity wins.

CSS – !important
/* !important beats everything in the normal cascade */
p { color: blue !important; }     /* wins over: */
#main p { color: red; }           /* even though (1,0,1) > (0,0,1) */

/* Two !important — specificity wins */
p { color: blue !important; }     /* (0,0,1) with !important */
.text { color: red !important; }  /* (0,1,0) with !important — wins */

/* Utility class pattern — legitimate use of !important */
.text-center { text-align: center !important; }
.hidden      { display: none !important; }
.mt-0        { margin-top: 0 !important; }

The Cascade Order

When specificity is equal, the cascade applies — rules are resolved in this order (later stages override earlier ones):

Text – Cascade order (lowest to highest)
1. Browser default stylesheet (user-agent styles)
2. User stylesheet (accessibility overrides in browser settings)
3. Author stylesheet (your CSS) — by order:
   a. External stylesheets (in link order)
   b. Internal