The Cascade, Specificity & Inheritance
The Cascade — Conflict Resolution
When multiple rules target the same element, CSS resolves the conflict in order of: importance → specificity → source order. Understanding this is the difference between styling deliberately and fighting your own stylesheet.
Specificity — the Scoring System
Think of specificity as three numbers (ids, classes, elements) compared left to right:
p /* (0,0,1) */
.intro /* (0,1,0) — beats any number of elements */
p.intro /* (0,1,1) */
.card .intro /* (0,2,0) */
#main /* (1,0,0) — beats any number of classes */
#main .card p /* (1,1,1) *//* Which colour wins? */
#main p { color: red; } /* (1,0,1) — wins */
.card p { color: blue; } /* (0,1,1) */Inline style="" beats everything in stylesheets; !important beats even that. Equal specificity → the later rule in the file wins.
Keep Specificity Low
High-specificity selectors are a trap: once you write #sidebar .widget ul li a, every future override must be even more specific. Professional CSS stays flat:
/* fragile */
#sidebar div.widget ul li a.link { color: blue; }
/* maintainable — single class, specificity (0,1,0) */
.widget-link { color: blue; }!important — the Emergency Brake
.btn { color: white !important; }It overrides everything — and the only way to beat an !important is another, more specific !important. That arms race destroys stylesheets. Legitimate uses: overriding third-party styles you don’t control, utility classes that must always win. Otherwise, fix the specificity instead.
Inheritance
Text-related properties flow down to children automatically: color, font-family, font-size, line-height, text-align. Box properties (margin, padding, border, background) do not.
body {
font-family: 'Inter', sans-serif; /* the whole page inherits */
color: #1F2937;
line-height: 1.6;
}Control inheritance explicitly with the keywords inherit, initial, and unset:
button { font: inherit; } /* buttons don't inherit fonts by default — fix it */A Sensible Reset
Browsers ship default styles that differ. Most projects start by flattening them:
*, *::before, *::after {
box-sizing: border-box; /* next topic explains this */
margin: 0;
padding: 0;
}
img { max-width: 100%; display: block; }