Lesson 13 of 32
The Cascade and Inheritance
How equal-specificity rules resolve by source order, which properties inherit down the document by default and which don't, and the inherit, initial and unset keywords.
You now know how the browser picks a winner when two selectors have different specificity — the higher one wins, full stop, no matter where either rule sits in the file. This lesson covers the two things that fill in the rest of the picture: what happens when specificity is genuinely equal, and how a value can reach an element without any rule targeting that element directly at all.
The cascade: source order breaks ties
"Cascade" is the C in CSS, and it's the mechanism for resolving conflicts. You already know its first rule from last lesson: higher specificity always wins, regardless of order. Its second rule is what happens when specificity is a genuine tie:
p { color: blue; }
p { color: green; }Both selectors are a lone type selector — identical specificity. The second
rule is written later in the source, so it wins: the text is green. Move the
color: green rule above color: blue in the file, and the result flips.
Order only matters as a tie-breaker after specificity has already failed
to produce a winner — a p { color: red; } written at the very end of the
file still loses to a .message { color: blue; } written at the very top,
because a class always outweighs a type selector regardless of position.
This is also why <link>ed stylesheets and <style> blocks that appear
later in a document can override ones that appear earlier — the browser
treats them as one continuous, ordered set of rules.
Inheritance: some properties flow down for free
Some CSS properties, when left unset on an element, take their value from the nearest ancestor that does set it, rather than falling back to a browser default. This is inheritance, and it's separate from the cascade — it's not about two rules conflicting, it's about a value travelling down the document tree with no rule targeting the child at all.
body { color: #222; font-family: system-ui, sans-serif; }<body>
<p>This text is #222 and system-ui, with no rule mentioning <p> at all.</p>
</body>Every element inside <body> inherits color and font-family from it,
because both properties are inheritable. Nothing on <p> itself set them —
the value simply flowed down.
Properties that inherit by default: text and typography properties —
color, font-family, font-size, font-weight and the rest of the
font-* family, line-height, text-align, and the list-style-*
properties.
Properties that do not inherit by default: box model properties —
margin, padding, border, width, height — along with background
and display.
That split isn't arbitrary. Text properties cascading down an entire
document is almost always what you want — set a font and a base colour once
on body, and every paragraph, list item and heading picks it up without
you repeating yourself. A box's own spacing, on the other hand, is rarely
something you want copied onto every descendant: if margin inherited by
default, giving one <div> a 2rem margin would push margin onto every
element nested inside it too, which is almost never the intent. Each box
manages its own spacing; only text-level styling is expected to flow.
inherit, initial, and unset
Three keywords let you control this explicitly, as a value for any property:
.child {
color: inherit; /* explicitly take the parent's computed value */
margin: initial; /* reset to the property's own default, ignoring the parent entirely */
border: unset; /* act like inherit if the property normally inherits, otherwise like initial */
}inheritforces a property to take its parent's computed value, even if that property doesn't normally inherit. Useful for something likeborder-color: inheritwhen you want a child's border to match its parent's text colour exactly.initialresets a property to its specification-defined default, ignoring whatever the parent has.color: initialresets to the browser's base black-ish default, not the parent's colour.unsetis the pragmatic middle ground: it behaves likeinheriton properties that inherit by default, and likeinitialon properties that don't. It's the closest thing to "forget every rule that touched this and go back to how it would behave naturally."
Shorthand properties, and their real gotcha
A shorthand property sets several longhand properties in one declaration.
margin is the clearest example:
margin: 10px 20px;
/* equivalent to: */
margin-top: 10px;
margin-right: 20px;
margin-bottom: 10px;
margin-left: 20px;Two values means top/bottom, then left/right. Four values go clockwise from
the top: margin: 10px 20px 30px 40px is top, right, bottom, left.
The gotcha, and it's a real and common one: a shorthand resets every longhand it covers, even the ones you didn't mention.
.card {
margin: 20px; /* sets all four sides to 20px */
margin-top: 40px; /* only top is overridden — right/bottom/left stay 20px, fine */
}That example is safe, because the shorthand comes first. This one isn't:
.card {
margin-top: 40px; /* intent: a bigger top margin */
margin: 20px; /* this resets margin-top back to 20px too — the line above is wiped out */
}If margin: 20px appears after margin-top: 40px, it silently overwrites
the top value back to 20px, because the shorthand sets all four sides
unconditionally — it doesn't know or care that you'd already set one of them
on purpose. This is one of the most common real-world sources of "I set this
and it's being ignored" bugs, and the fix is either to reorder the
declarations (shorthand first, specific override after) or to only use the
longhand once you're overriding a single side.
Try it yourself
body sets color and font-family once, and every element below inherits
them without a single extra rule. Watch what happens to the box model
properties (background, border, padding) instead — none of those travel
down, so each box states its own.
What to remember
- When specificity is equal, the cascade falls back to source order — later wins. Specificity itself still always wins over order when the two differ.
- Text properties (
color,font-*,line-height,text-align,list-style-*) inherit by default; box model properties,background, anddisplaydo not. inheritforces a parent's value,initialresets to the spec default,unsetpicks whichever of those two behaviours is natural for that property.- A shorthand like
margin: 10px 20pxresets every longhand it covers — order your shorthand and longhand declarations carefully, or a later shorthand will silently undo an earlier specific override.
Check yourself
4 questions · pass 3/4 to unlock The Box Model
1.Two rules both target the same element with the same specificity and set conflicting values for the same property. Which one wins?
2.Which of these properties is inherited by default?
3.What does
color: inheritdo on an element whose parent hascolor: red?4.Why does
margin: 10px 20px;followed later bymargin-top: 5px;still leave margin-right, bottom and left at the shorthand's values?
4 left to answer