Topic 2.3
Inheritance
In one line
Some properties, mostly about text such as color and font, pass from a parent element to its children automatically; the rest do not. The keywords inherit, initial, unset and revert let you control this on purpose.
Think of it like this
A family. Children often inherit their parents' language and accent without anyone teaching them each word. But they don't inherit their parents' coats: each child gets their own. In CSS, text-related properties like color and font-family are like the language (passed down), and box-related properties like border and padding are like the coats (each element has its own).
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Parent and child
- An element directly inside another is its child; the outer one is its parent.
- Inheritance
- When an element takes a property's value from its parent because no rule set it.
- Inherited property
- A property that passes down by default, like
colororfont-family. - Initial value
- The built-in default value the CSS specification gives each property, like
transparentforbackground-color. - Computed value
- A value after the browser has worked out relative units, like
2embecoming32px. - inherit
- A keyword that forces an element to use its parent's value for a property.
- initial
- A keyword that resets a property to the specification's initial value.
- unset
- A keyword meaning "as if no rule set this": inherit if the property is inherited, otherwise initial.
- revert
- A keyword that rolls a property back to the browser's default style for that element.
Step by step
01Set text styles once, on the body
Because color, font-family and line-height are inherited, one rule on body styles the whole page's text. Every element that doesn't set them itself takes them from its parent, which took them from its parent, all the way up.
body {
color: #222;
font-family: system-ui, sans-serif;
line-height: 1.5;
}02Notice what does not flow down
Add border: 2px solid tomato to a div. Only the div gets a border; its paragraphs don't. border is not inherited, so the paragraphs use the initial value border-style: none.
03A declaration always beats inheritance
Inheritance is only used when the cascade found no declaration. Any matching rule, even the browser's default a { color: -webkit-link } or a weak * selector, wins over the inherited value. That's why links stay blue inside a red paragraph.
.warning { color: red; }
/* <p class="warning">Read <a href="#">this</a></p>
the link stays blue: the browser's a { color } rule beats inheritance */
.warning a { color: inherit; } /* now the link follows the paragraph */04Use the four keywords
Each keyword answers a different question: inherit ("copy my parent"), initial ("use the spec's default"), unset ("act as if I wrote nothing"), revert ("go back to the browser's default").
a.plain { color: inherit; } /* parent's colour */
div.x { display: initial; } /* inline! the spec default */
div.y { display: unset; } /* not inherited, so initial: inline */
div.z { display: revert; } /* browser default for div: block */
.card * { all: unset; } /* every property at once */05Reset form controls
Write this once in your stylesheet so buttons and inputs match the page's text instead of the browser's control font.
button,
input,
select,
textarea {
font: inherit;
color: inherit;
}Try it yourself
- 1
Inherit the border on purpose
In the first example, predict what
p { border: inherit; }does. Then add it. The paragraph now draws its own tomato border inside the box's border, and the console reports3px. - 2
Fix the button
In the first example, add
button { font: inherit; color: inherit; }. Run it: the button now uses Georgia and navy, and both questions printtrue. - 3
Break the line-height
In the third example, change
.bigtofont-size: 48px. Predict the two line-heights before running (72px and still 24px).
Code & diagrams
Add `button { font: inherit; color: inherit; }` to the CSS and run again: the last two lines turn `true`.
Preview
Console
Nothing logged yet.Expected console output
Paragraph colour is navy? true
Paragraph font: Georgia, serif
Paragraph border width: 0px
Button uses the box font? false
Button colour is navy? false`color` is inherited, so `unset` behaves like `inherit`. `display` is not inherited, so `unset` behaves like `initial`, which is `inline`. Only `revert` gives a div back its normal `block`.
Preview
Console
Nothing logged yet.Expected console output
color: inherit -> seagreen
color: initial -> black
color: unset -> seagreen
color: revert -> seagreen
display: initial -> inline
display: unset -> inline
display: revert -> blockWith 150%, the parent turns it into 24px and the 32px child inherits 24px, so its lines overlap. With 1.5, the child inherits the ratio and gets 32 × 1.5 = 48px.
Preview
Console
Nothing logged yet.Expected console output
line-height: 1.5 on the parent -> child line-height 48px
line-height: 150% on the parent -> child line-height 24pxBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Use display: initial to "reset" a div
A rule set .panel { display: flex; } and you want one panel back to normal, so you write .panel.simple { display: initial; }.
Break #2
A link that won't take the paragraph's colour
Write .alert { color: white; background: crimson; } on a paragraph that contains a link.
Myth vs fact
Myth
Every property is inherited.
Fact
Only some are, mostly text properties. Box and layout properties like margin, padding, border, background and width are not.
Myth
initial means the browser's default for that element.
Fact
initial is the specification's default for the property, the same for every element. The per-element browser default is what revert gives you.
Myth
Inheritance beats a weak selector like *.
Fact
Inheritance has no strength at all. It is only used when the cascade found no declaration. * { color: black } beats a colour inherited from body.
Myth
opacity and text-decoration are inherited because children change too.
Fact
Neither is inherited. With opacity, the parent and all its children are painted as one group and then faded. With text-decoration, the parent's underline is drawn across its children's text. Setting the property on a child can't undo either.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Inheritance passes the computed value through the element tree (the DOM, including Shadow DOM: a component's shadow content inherits from its host). That is why CSS custom properties, which are inherited, are the standard way to theme Web Components.
- ▸
visibilityis inherited but can be overridden: a child withvisibility: visibleshows inside avisibility: hiddenparent.display: noneis not inherited, yet it removes the entire subtree, which no child can undo. - ▸
all: unsetresets every property exceptdirectionandunicode-bidi(and doesn't touch custom properties).all: revertis usually what people want for "undo the author styles on this widget", becauseunsetalso strips the browser's useful defaults, such asdisplay: blockand list bullets. - ▸
Browsers optimise inheritance by sharing computed style objects between siblings with identical styles, so setting text styles high in the tree (on
bodyor a component root) is cheap and keeps the style data small.
Remember this
- 1
Elements are nested: a
<p>inside a<div>is the div's child, and the div is its parent. Inheritance means: when the cascade finds no declaration for an inherited property on an element, the element takes the value its parent has. Setcolor: navyonbodyand every paragraph, list and heading inside turns navy, without one rule each. - 2
The specification marks every property as inherited or not inherited. Inherited ones are mostly about text:
color,font-family,font-size,font-weight,font-style,line-height,letter-spacing,text-align,text-indent,text-transform,white-space,visibility,cursor,list-style,direction,border-collapseand all custom properties (--brand, Topic 3.6). Not inherited: box and layout properties such asmargin,padding,border,background,width,height,display,position,overflow,opacityandtransform. Imagine aborderthat was inherited: every child would draw its own border inside the parent's. - 3
A non-inherited property with no declaration gets its initial value, the default written in the specification for that property:
border-style: none,background-color: transparent,display: inline,margin: 0. (Headings and paragraphs have margins only because the browser's default stylesheet gives them some.) - 4
Children inherit the parent's computed value, the value after relative units are worked out. If the parent has
font-size: 2emand that computes to32px, children inherit32px, not "2em". This is also whyline-height: 1.5(a plain number) is better thanline-height: 150%: the number is inherited as a ratio and recalculated for each child's font size, while the percentage is turned into a fixed length on the parent and inherited as that length. - 5
Four keywords work on every property and let you choose:
inherittakes the parent's value, even for a non-inherited property (border: inherit).initialuses the specification's initial value (watch out:display: initialisinline, even on adiv).unsetacts likeinheritfor inherited properties and likeinitialfor the rest, as if no rule had been written.revertrolls the property back to what the browser's default stylesheet would give it (display: reverton adivgivesblock). A fifth,revert-layer, rolls back to the previous cascade layer (Topic 2.5). - 6
Form controls (
button,input,select,textarea) are the famous exception in practice.fontis an inherited property, but the browser's default stylesheet sets a font on these elements, and any declaration beats inheritance. So buttons ignore yourbodyfont until you writebutton, input, select, textarea { font: inherit; }, a line found in almost every CSS reset.
Explain it without notes
What is inheritance in CSS, and when does it apply?
Give five inherited and five non-inherited properties, and explain why border is not inherited.
Explain the difference between inherit, initial, unset and revert using display on a div.
Why is line-height: 1.5 recommended over line-height: 150%?
Practice
Set the whole page's text to dark gray #333, the font to Georgia, serif and the line-height to 1.6 with a single rule, and make buttons use the same font and colour.
A navigation bar has a dark background and white text: .nav { background: #222; color: white; }. Its links are still blue. Fix it so the links are white, without writing white twice.
Trade-offs
- ↔
Setting text styles once on
bodyand letting them inherit keeps CSS short, but makes a component's look depend on where it is placed; setting them on the component itself is more predictable but repeats values (custom properties, Topic 3.6, are the middle ground). - ↔
all: unsetgives a clean slate for a custom widget but strips accessibility-relevant defaults like focus outlines anddisplay: block;all: revertkeeps browser defaults but leaves more to override.
Done when you can
I can say whether a common property is inherited or not.
I know inheritance only applies when no declaration matched.
I can use
inherit,initial,unsetandrevertcorrectly.I know children inherit computed values, and why
line-heightshould be a number.I can make form controls use the page font.