CSS Specificity & Architecture
When your rule "doesn't work," specificity is usually why. Learn the scoring, the !important trap, and the naming conventions that keep 10,000-line stylesheets sane — this is CSS as engineering.
1. The scoring system
| Selector part | Score column | Example |
|---|---|---|
| Inline style | 1-0-0-0 | style="…" |
| ID | 0-1-0-0 | #hero |
| Class / attribute / pseudo-class | 0-0-1-0 | .card, :hover |
| Element / pseudo-element | 0-0-0-1 | p, ::before |
Compare column by column, left to right — one ID (0-1-0-0) beats any number of classes (0-0-99-0). nav .link:hover scores 0-0-2-1. Ties fall to source order. And !important jumps the whole queue — which is exactly why it breeds more !important; treat it as a last resort, not a tool.
2. Architecture: keeping it flat
/* Block __Element --Modifier */
.card { }
.card__title { }
.card__button { }
.card--featured{ }Professional stylesheets stay overridable by staying flat: single-class selectors everywhere, so any rule can be beaten by any later rule. BEM naming encodes structure into the class name instead of the selector chain. Avoid styling IDs; avoid deep descendant chains; group your files base → layout → components → utilities. Modern CSS adds :where(), which contributes zero specificity — handy for resets.
3. Try it yourself
The button stubbornly stays gray because an ID rule outguns your class. Fix it properly: change the #actions button selector into a flat class-based one so .btn-primary can win. (No !important allowed!)
4. Quiz — check your understanding
CSS Specificity & Architecture Quiz
4 questions · pass at 60%Q1. Which selector wins: #nav a or .nav .list .item a:hover?
Q2. .card:hover::before scores…
Q3. Why is !important discouraged?
Q4. In BEM, .card__title is…
Every lesson quiz you pass (60%+) is saved in your browser and counts toward the CSSmatic Certificate of Completion.