Specificity explains why one CSS rule wins over another. When styles do not apply as expected, the issue is often not that CSS is broken; it is that another selector is stronger or appears later in the cascade.
The goal is not to write the strongest selector. The goal is to write selectors that are strong enough to target the right element but still easy to override later.
Add one worked example that compares the normal path with the boundary case for CSS Specificity Cascade How It Works.
CSS Specificity Cascade How It Works should be studied as a practical CSS lesson, not as a label. Start by naming the input, the rule that changes the input, and the result a learner should be able to predict after reading the page.
In the css > specificity page, the notes should connect the definition with a working scenario, a mistake that beginners actually make, and the exact check that proves the fix. That makes the topic useful for coding, debugging, and interview revision.
When multiple CSS rules target the same element, the browser uses specificity to determine which rule wins. Specificity is calculated as a score - the rule with the highest score is applied.
Specificity is calculated using four categories (A, B, C, D):
| Category | What counts | Score |
|---|---|---|
| A - Inline styles | style="..." attribute | 1,0,0,0 |
| B - ID selectors | #id | 0,1,0,0 |
| C - Class, attribute, pseudo-class | .class, [attr], :hover | 0,0,1,0 |
| D - Element, pseudo-element | div, p, ::before | 0,0,0,1 |
/*
* Specificity scores (A, B, C, D):
*
* * -> 0,0,0,0 (universal)
* p -> 0,0,0,1 (element)
* .class -> 0,0,1,0 (class)
* #id -> 0,1,0,0 (ID)
* style="" -> 1,0,0,0 (inline)
*
* p.class -> 0,0,1,1 (element + class)
* div p -> 0,0,0,2 (2 elements)
* .nav .link -> 0,0,2,0 (2 classes)
* #header .nav a -> 0,1,1,1 (ID + class + element)
* #header #nav -> 0,2,0,0 (2 IDs)
*/
/* Which color wins? */
p { color: blue; } /* 0,0,0,1 */
.text { color: green; } /* 0,0,1,0 - wins over p */
#main { color: red; } /* 0,1,0,0 - wins over .text */
/* inline style="color: orange" - wins over #main */
/* !important - overrides everything (use sparingly!) */
p { color: blue !important; } /* wins even over inline styles */
/* Specificity tie - last rule wins */
.btn { background: blue; }
.btn { background: red; } /* wins - same specificity, later in file */
/* Practical: avoid high specificity chains */
/* BAD - hard to override */
#sidebar .widget ul li a { color: blue; }
/* GOOD - low specificity, easy to override */
.sidebar-link { color: blue; }
The cascade determines which CSS rule applies when multiple rules conflict. It considers three factors in order:
Low-specificity CSS is easier to maintain. Utility classes, component classes, and modern helpers like :where() can keep selectors predictable.
/* Inheritance - some properties inherit from parent */
/* Inherited: color, font-*, line-height, text-*, visibility */
/* Not inherited: margin, padding, border, background, width, height */
body {
color: #333; /* all text inherits this color */
font-family: Arial; /* all text inherits this font */
}
/* inherit keyword - force inheritance */
.child {
border: inherit; /* inherit border from parent (not normally inherited) */
color: inherit; /* explicitly inherit color */
}
/* initial keyword - reset to browser default */
.reset {
color: initial; /* resets to browser default (usually black) */
font-size: initial; /* resets to browser default (usually 16px) */
}
/* unset keyword - inherit if inheritable, else initial */
.unset {
color: unset; /* inherits (color is inheritable) */
margin: unset; /* initial (margin is not inheritable) */
}
/* revert keyword - reset to browser stylesheet value */
.revert {
all: revert; /* reset ALL properties to browser defaults */
}
/* Specificity best practices */
/* 1. Keep specificity low - use classes, not IDs */
/* 2. Avoid !important - it breaks the cascade */
/* 3. Use :is() and :where() for complex selectors */
/* :is() - matches any selector in list, takes highest specificity */
:is(h1, h2, h3) { margin-top: 0; }
/* :where() - same but ZERO specificity (easy to override) */
:where(h1, h2, h3) { margin-top: 0; }
CSS Specificity Cascade How It Works matters in CSS because it changes how a program is written, tested, or debugged. The page should explain the normal flow first: what the developer writes, what the runtime or platform does, and what result should appear.
When teaching CSS Specificity Cascade How It Works, avoid stopping at syntax. Show the surrounding decision: why this feature is chosen, what problem it removes, and what would become harder if the feature were not used.
.lesson-box {
display: block;
max-width: 42rem;
padding: 1rem;
}
.lesson-box:empty::before {
content: "CSS Specificity Cascade How It Works: add visible content";
}
Fixing a conflict by adding more and more selector nesting.
Simplify selectors and adjust source order or component class names.
Using !important for normal component styling.
Find the competing selector and make the cascade cleaner.
Assuming later rules always win.
Remember that source order only wins when specificity is equal.
Memorizing CSS Specificity Cascade How It Works without the situation where it is useful.
Connect CSS Specificity Cascade How It Works to a concrete CSS task.
No. Source order matters only after importance and specificity are equal.
IDs have high specificity, which makes later overrides harder.
It is not always bad, but it should be used deliberately because it can make future overrides difficult.
Open DevTools, inspect the element, and check which declarations are crossed out in the styles panel.
Explore 500+ free tutorials across 20+ languages and frameworks.