skip to content

Inheritance and Global Values

Which properties inherit by default, and how to force the behavior you want with the global keywords. The difference between initial and revert catches most candidates, and "why did my button not inherit the font" is a classic follow-up.

part ofCSSoverview, primer and where to startread it →
on this pageshow

questions

5

In CSS, which kinds of properties are inherited by default and which are not, and how does inheritance differ from the cascade?

level: juniorimportance: must knowfreq 70%

answer

  1. typography flows down, boxes do not
  2. spec says Inherited: yes or no
  3. cascade first, inheritance only fills gaps
  4. visibility inherits, opacity does not
  5. a UA declaration blocks inheritance

basics

~10 s

Text-related properties inherit by default: color, the font properties, line-height, letter-spacing, text-align, white-space, list-style, visibility and cursor. Box and painting properties do not: margin, padding, border, background, width, height, display, position, overflow.

solid answer

~40 s

The rough rule is that properties describing **text** inherit and properties describing the **box** do not. So `color`, the `font-*` family, `line-height`, `letter-spacing`, `text-align`, `white-space`, `list-style`, `visibility` and `cursor` flow down the tree, while `margin`, `padding`, `border`, `background`, `width`, `height`, `display`, `position` and `overflow` stop at the element they are set on. Inheritance is not the cascade. The cascade picks a winner among declarations that target the *same* element; inheritance runs afterwards, only for properties where no declaration reached that element at all. That is why a browser-default declaration on a form control blocks inheritance entirely. Every property's specification (and its MDN page) states "Inherited: yes/no" — that line is the authority, not intuition. You can override either default with the `inherit` or `initial` keywords.

code

html · 4 lines
html
<section style="font-family: Georgia, serif; padding: 24px; border: 2px solid teal">
  <p>Inherits the serif font, but not the padding or the border.</p>
  <p style="border: inherit">This one is forced to inherit the border.</p>
</section>

go deeper

for a junior

Be ready to sort properties into the two buckets on the spot: font and text properties inherit, box properties do not. Say plainly that inheritance only applies when no rule sets the property on that element.

for a middle

Explain the defaulting step: inherited property with no declaration takes the parent's computed value, otherwise the property's initial value. Be able to explain why opacity fades children without inheriting.

for a senior

Show how you diagnose it — read the computed pane in DevTools to tell an inherited value from a matched rule, and recognise user-agent declarations as the usual reason inheritance appears not to happen.

for a principal

Frame it as a design decision for the stylesheet: what you deliberately let cascade from the root (type scale, color, text rendering) versus what every component must declare for itself so it stays portable between contexts.

## Two separate steps For every element and every property the browser must end up with exactly one value, and it gets there in two distinct steps. First the **cascade** collects all declarations that target *this element* for *this property* — from the browser's user-agent stylesheet, from the user, and from your author styles — and sorts them by origin, importance, cascade layer, specificity and source order. If any declaration survives, that is the value and inheritance never enters the picture. If nothing targeted the element, **defaulting** runs. Here the inherited/not-inherited flag matters: for an inherited property the element takes the *parent's computed value*; for a non-inherited property it takes the property's **initial value** as defined in the specification. The root element has no parent, so an inherited property there also falls back to the initial value. This ordering explains most "why didn't it inherit" bugs: an element that already has a declaration — including one you never wrote, from the user-agent stylesheet — has nothing left to inherit. ## The two columns **Inherited (text-ish):** `color`, `font-family`, `font-size`, `font-weight`, `font-style`, `line-height`, `letter-spacing`, `word-spacing`, `text-align`, `text-indent`, `text-transform`, `white-space`, `direction`, `list-style` and its longhands, `quotes`, `cursor`, `visibility`, `caret-color`, `border-collapse`, `border-spacing`, and — surprisingly to many — `text-shadow`. **Not inherited (box-ish):** `margin`, `padding`, `border`, `background` and its longhands, `width`, `height`, `min-*`/`max-*`, `display`, `position` and the inset properties, `float`, `overflow`, `z-index`, `opacity`, `box-shadow`, `vertical-align`, and every Flexbox and Grid property. The split has a logic to it. Typography is a document-wide intent: set the body font once and the whole page follows. Box geometry is per-element; a paragraph inheriting its section's `width: 800px` or its `padding: 40px` would be chaos. ## The classic traps **`opacity` does not inherit, yet children look faded.** `opacity: 0.5` on a parent makes the browser render the entire subtree into one layer and composite that layer at 50%. The children's computed `opacity` is still `1`; the fading is a painting effect, not inheritance. A child cannot undo it with `opacity: 1`. **`visibility` *does* inherit, and a child can undo it.** With `visibility: hidden` on a parent, a descendant that sets `visibility: visible` reappears — it inherited `hidden`, then overrode it. `display: none` behaves oppositely: it is not inherited, but the subtree generates no boxes at all, so nothing can bring a child back. **`background` does not inherit.** A child with no background of its own is transparent, so the parent's background simply shows through — visually similar, mechanically different. **`text-decoration-line` does not inherit**, but a decoration drawn on an ancestor is painted across its in-flow descendant inline boxes, which is why you cannot remove an underline from a `<span>` inside an underlined block. ## Forcing the behaviour you want Any property accepts `inherit`, which takes the parent's computed value regardless of the property's default flag. `div { border: inherit; }` is legal and does inherit. Conversely `initial` throws away an inherited value and uses the specification's initial value. This is exactly how resets make form controls follow the page font: ```css button, input, select, textarea { font: inherit; } ``` ## Checking rather than guessing Do not memorise the list; memorise the rule of thumb and check the edge cases. Both the specification and MDN print an "Inherited" row in the formal-definition table of every property page, and DevTools shows an element's computed value plus which rule produced it, so an inherited value is visible as coming from an ancestor rather than from a matched rule.

  • If opacity is not inherited, why do all the children of an element with opacity: 0.5 look faded?
    Because `opacity` below 1 makes the browser render the element and its whole subtree into a single layer and composite that layer at the given alpha. The children's computed `opacity` is still `1` — the fading is a painting effect, so a child cannot restore itself with `opacity: 1`. Contrast that with `visibility: hidden`, which genuinely inherits and *can* be undone by a descendant setting `visibility: visible`.
  • Can you make a normally non-inherited property inherit?
    Yes — every property accepts the `inherit` keyword, which takes the parent's computed value no matter what the property's default flag says. `.child { border: inherit; padding: inherit; }` is perfectly valid. The flag only decides what happens when *no* declaration reaches the element; an explicit `inherit` is a declaration like any other and wins through the normal cascade.
  • Where does an inherited property get its value on the root html element, which has no parent?
    From the property's initial value in the specification, since there is no parent computed value to take. In practice you rarely see the raw initial value because the user-agent stylesheet declares quite a lot on `html` and `body`, and those declarations cascade normally — they are not inheritance.

saying these in an interview costs you the question

  • Says every CSS property inherits from its parent
  • Thinks width and height are inherited by children
  • Claims opacity is inherited because children look faded
  • Uses cascade and inheritance as synonyms
  • Believes display: none is inherited by descendants

context

open as a page

In CSS, what is the difference between the global keywords inherit, initial, unset, and revert?

level: middleimportance: must knowfreq 60%

basics

~20 s

inherit takes the parent's computed value; initial uses the property's spec-defined initial value; unset means inherit for inherited properties and initial for the rest; revert rolls the property back to the user-agent or user value, discarding author styles.

open as a page

In CSS, why does line-height: 1.5 on a container behave differently for descendants than line-height: 150%?

level: middleimportance: should knowfreq 42%

basics

~20 s

Inheritance passes the parent's computed value. A unitless line-height computes to the number itself, so each descendant multiplies it by its own font-size; a percentage resolves to a fixed length on the parent, and every descendant inherits that same length.

open as a page

A page sets font-family on body, yet the site's buttons and inputs still render in the browser's default font. Why does inheritance not reach them, and what is the standard fix?

level: middleimportance: should knowfreq 52%

basics

~10 s

The user-agent stylesheet declares font on form controls, and inheritance only applies when no declaration reaches an element. The fix is to opt back in explicitly: button, input, select, textarea { font: inherit; }.

open as a page

You embed a widget's markup into pages whose CSS you do not control. Using CSS's all shorthand, how do all: initial, all: unset and all: revert differ as the widget's reset, and what does all not cover?

level: seniorimportance: nice to knowfreq 26%

basics

~20 s

all sets every property to one global keyword: initial gives the specification's blank slate (display becomes inline), unset lets inherited properties come from the host page, and revert restores user-agent styles. all skips direction, unicode-bidi and custom properties, and applies to one element only.

open as a page