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?
answer
- inheritance only runs when nothing cascaded
- the user-agent stylesheet already declared it
- controls get a font shorthand, not just family
- font: inherit, not font-family: inherit
- DevTools shows the user agent stylesheet rule
basics
~10 sThe 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; }.
solid answer
~40 sInheritance is not a fallback that competes with other rules — it only runs when the cascade produced **no** value for that property on that element. Browsers ship a user-agent stylesheet that declares the `font` shorthand on `button`, `input`, `select` and `textarea`, historically so controls matched the operating system's widgets. Because a declaration exists, there is nothing left to inherit, and your `body { font-family: ... }` never reaches them. The fix is to opt back in explicitly: `button, input, select, textarea { font: inherit; }`. Using the `font` shorthand matters, since the UA rule is also a shorthand and sets `font-size`, `font-weight` and `line-height` too; `font-family: inherit` alone leaves you with a 13px button in a 16px page. Most CSS resets include exactly this rule, and `color: inherit` is often added alongside it.
code
css · 7 linesbody { font-family: Inter, system-ui, sans-serif; font-size: 16px; }
/* Without this, controls keep the browser's ~13px platform font */
button, input, select, textarea {
font: inherit;
color: inherit;
}go deeper
Recognise the symptom and know the one-line fix: add font: inherit to button, input, select and textarea. Be able to say the browser's own stylesheet already set the font there.
Explain the mechanism — inheritance only runs when the cascade produced nothing for that property on that element — and why the shorthand form of the fix matters for size and line-height.
Show you can diagnose it live in DevTools by tracing the computed value to a user-agent rule, and argue why you keep native border, padding and focus ring instead of wiping the control.
Take a position on reset policy: how much user-agent styling the codebase normalises globally versus per component, and the accessibility and maintenance cost of stripping native control affordances.
## Inheritance only fills a vacuum The order matters: the cascade runs first, considering every declaration that targets this element for this property, from any origin — user-agent, user, or author. Only if that produces nothing does defaulting run, and only then does an inherited property look at its parent. The user-agent stylesheet is a real stylesheet with real declarations. It is the weakest origin, so any author rule beats it — but *only if an author rule exists for that property on that element*. A `body`-level declaration does not target the button. From the button's point of view the only declaration in play is the UA one, so the UA one wins, and inheritance never gets a turn. This is the general shape of nearly every "why did it not inherit" bug: something already declared the property on that element. ## What the browser actually declares UA stylesheets for form controls set the `font` shorthand to a platform-flavoured value. In Chromium the button rule has long resolved to something close to `font: 400 13.333px Arial`; Firefox and Safari use their own values, and modern builds increasingly reference system font keywords. The exact value is not the point and is not worth memorising — what matters is that **a declaration exists**, and that it is a shorthand, so it sets `font-style`, `font-weight`, `font-size`, `line-height` and `font-family` all at once. That is also why the same controls do not pick up your `color`, and why `text-align` inside a `<button>` is centred: those are separate UA declarations doing the same thing. ## The fix, and why the shorthand ```css button, input, select, textarea { font: inherit; } ``` `font: inherit` expands to `inherit` on every font longhand plus `line-height`, so the control adopts the page's whole type treatment. Writing only `font-family: inherit` fixes the typeface but leaves the UA's `font-size` in place, giving you a 13px control on a 16px page — a very common half-fix that looks broken at larger text sizes and hurts readability. Add `color: inherit` when you want the control's text colour to follow the page too, and remember `line-height` comes along with the `font` shorthand, so if you rely on a global unitless `line-height`, controls now share it. ## What this rule does not do `font: inherit` changes typography only. The control keeps its native background, border, padding and focus ring, which is usually what you want — those are what make it recognisable and keyboard-friendly. If you want a fully custom control you style those properties deliberately, rather than wiping everything with `all: unset`, which also removes the focus indication and the pointer cursor and leaves you re-implementing affordances by hand. Also note this is styling only: which element to use for a control, and the semantics it carries, are separate questions from how it inherits type. ## Related surprises with the same cause - A `<textarea>` does not inherit `font-family` for the same reason, and additionally has its own `white-space` behaviour. - `<select>` and its `<option>` children are rendered partly by the platform in some browsers, so even `font: inherit` may not reach every part of the dropdown. - Headings do not inherit `font-size` from `body` — the UA stylesheet declares `h1 { font-size: 2em; }` and friends. Same mechanism, different element. - `<table>` historically did not inherit font in old browsers for the same reason; that particular UA rule is gone in modern engines. ## Diagnosing it in seconds In DevTools, select the control and look at the Computed pane for `font-family`. If the value traces to a `user agent stylesheet` rule rather than showing as inherited from an ancestor, you have your answer immediately — and the same trick identifies any other property that mysteriously refuses to inherit.
- Why is font: inherit preferred over font-family: inherit here?Because the user-agent rule is itself the `font` shorthand, so it also set `font-size`, `font-weight` and `line-height`. Overriding only `font-family` leaves the control at the browser's default size — roughly 13px against a 16px page — which looks wrong and scales badly when the user increases text size. `font: inherit` neutralises the whole shorthand in one declaration.
- Would button { all: unset } solve this more thoroughly?It fixes the font but goes much too far: it removes the background, border, padding, focus ring and pointer cursor, and turns the button inline. The control stops looking clickable and loses its visible focus indication unless you rebuild all of it. If you want a genuine reset, `all: revert` keeps the native control; for typography alone, `font: inherit` is the targeted fix.
- Why do h1 and h2 not inherit body's font-size either?Same mechanism: the user-agent stylesheet declares `h1 { font-size: 2em; }` and equivalents for the other levels, so a declaration already exists on those elements and inheritance never runs for that property. They do inherit `font-family`, because the UA rule sets only size and weight — which is why headings follow your page font but not your page size.
saying these in an interview costs you the question
- Claims font-family is not an inherited property
- Says form control text is drawn by the OS, not CSS
- Fixes it with font-family: inherit and leaves the size wrong
- Reaches for !important instead of a plain declaration
- Thinks inheritance competes with the cascade and lost