---
layout: post
title: "font-family Doesn’t Fall Back the Way You Think"
date: 2026-04-10 11:30:00
categories: Web Development
main: ""
meta: "A quick but important reminder that font-family declarations don’t inherit fallback stacks the way many developers assume."
---
There is a small but surprisingly important nuance in the way `font-family`
works that seems to catch a lot of people out. In my continuing series on [web
performance](/2026/04/what-is-css-containment-and-how-can-i-use-it/) for [design
systems](/2026/03/when-all-you-can-do-is-all-or-nothing-do-nothing/), today
we’ll look at font stacks and how, when improperly configured, they can cause
unsightly flashes of inappropriate or unexpected fallback text, and in more
extreme cases, layout shifts.
Correctly, developers for the most part know that `font-family` is an inherited
property: set a font family on the `:root`/`html`/`body` and, unless told
otherwise, descendants will inherit that font:
```css
body {
font-family: system-ui, sans-serif;
}
```
So far, so good!
The confusion tends to arrive when we introduce a web or custom font on a child
element, e.g.:
```css
h1 {
font-family: "Open Sans";
}
```
At a glance, this can feel perfectly sensible. The page should use `system-ui,
sans-serif`; the heading uses `"Open Sans"`; and while the web font is loading,
the browser will presumably just fall back to the parent’s stack—`system-ui,
sans-serif`.
Unfortunately, that isn’t the case.
## `font-family` Fallbacks Are Self-Contained
Once you declare a `font-family` on an element, that declaration stands on its
own. The element does not say: I would like `"Open Sans"`, and if that is
unavailable right now, please work your way back up the DOM and inherit whatever
fallbacks the nearest ancestor might have.
Instead, it says: My `font-family` is `"Open Sans"`.
And that’s all it
says.
And if the browser does not yet have `"Open Sans"` available (yet), it resolves
fallback from _that declaration_, not from the parent’s.
Put another way:
```css
h1 {
font-family: "Open Sans"; /* « The fallback happens inside here… */
}
/**
* …not here.
*/
body {
font-family: system-ui, sans-serif;
}
```
## Why You Get a Flash of Times
If the current element’s `font-family` declaration contains only one value, and
that value is not currently available, the browser falls back to its default
**for that element**, and not to an inheritable `font-family` from somewhere
higher up. For most browsers in their default state, that fallback is likely
_Times_ or _Times New Roman_. That is why you so often see a brief flash of
Times New Roman where you were expecting something much more sympathetic or
appropriate.
The browser is not _forgetting_ the parent’s font stack; it’s obeying the
child’s declaration exactly as written, then exhausting the options available in
that declaration, and then falling back to the browser default.
## The Fix Is Simple
Whenever you specify a `font-family`, specify a **complete stack**. I’m looking
at a client’s site right now and I can see this right at the very top of their
CSS:
```css
:root {
--hero-hero: "Clan Pro";
--heading-x-large: "Clan Pro";
--heading-large: "Clan Pro";
--heading-medium: "Clan Pro";
--heading-medium-subtle: "Clan Pro";
--heading-small: "Clan Pro";
--heading-small-subtle: "Clan Pro";
--heading-x-small: "Clan Pro";
--paragraph-title-x-large: "Bernina Sans";
--paragraph-title-large: "Bernina Sans";
--paragraph-title-medium: "Bernina Sans";
--paragraph-title-small: "Bernina Sans";
--paragraph-title-x-small: "Bernina Sans";
--paragraph-body-x-large: "Bernina Sans";
--paragraph-body-large: "Bernina Sans";
--paragraph-body-medium: "Bernina Sans";
--paragraph-body-small: "Bernina Sans";
--paragraph-body-x-small: "Bernina Sans";
--label-3-x-large: "Clan Pro";
--label-2-x-large: "Clan Pro";
--label-x-large: "Clan Pro";
--label-large: "Clan Pro";
--label-medium: "Clan Pro";
--label-small: "Clan Pro";
--label-x-small: "Clan Pro";
}
```
At the very least, all of these simply need to read:
```css
:root {
--hero-hero: "Clan Pro", sans-serif;
--heading-x-large: "Clan Pro", sans-serif;
--heading-large: "Clan Pro", sans-serif;
--heading-medium: "Clan Pro", sans-serif;
--heading-medium-subtle: "Clan Pro", sans-serif;
--heading-small: "Clan Pro", sans-serif;
--heading-small-subtle: "Clan Pro", sans-serif;
--heading-x-small: "Clan Pro", sans-serif;
--paragraph-title-x-large: "Bernina Sans", sans-serif;
--paragraph-title-large: "Bernina Sans", sans-serif;
--paragraph-title-medium: "Bernina Sans", sans-serif;
--paragraph-title-small: "Bernina Sans", sans-serif;
--paragraph-title-x-small: "Bernina Sans", sans-serif;
--paragraph-body-x-large: "Bernina Sans", sans-serif;
--paragraph-body-large: "Bernina Sans", sans-serif;
--paragraph-body-medium: "Bernina Sans", sans-serif;
--paragraph-body-small: "Bernina Sans", sans-serif;
--paragraph-body-x-small: "Bernina Sans", sans-serif;
--label-3-x-large: "Clan Pro", sans-serif;
--label-2-x-large: "Clan Pro", sans-serif;
--label-x-large: "Clan Pro", sans-serif;
--label-large: "Clan Pro", sans-serif;
--label-medium: "Clan Pro", sans-serif;
--label-small: "Clan Pro", sans-serif;
--label-x-small: "Clan Pro", sans-serif;
}
```
Remember, any time you declare a `font-family`, declare the whole thing. Even if
that is just a broad
[``](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/generic-family)
And while this is the bare minimum, at least sans-serif web fonts will actually fall
back to sans.
To do a much more thorough job, you can simply [hire me](/contact/) to run my
Web Performance for Design Systems workshop.
## Why This Matters
At its most simple, this is a trivial visual issue: a nascent sans heading
briefly rendered in serif just looks wrong.
At the other end of the spectrum, it can have real knock-on effects on Core Web
Vitals: if the fallback face is excessively different in width, height, or
overall proportions, the eventual swap to the web font can have an impact on
your CLS scores.
## Closing Thoughts
If a `font-family` matters enough to override, it matters enough to define
properly. This is one of those small details that feels too small to matter
right up until you notice it everywhere.
My client has had complaints of noticeable layout shifts while migrating to
a new design system, and at the size and scale they’re working at, they were
really, really struggling to pin it down. It only took me a few minutes because
_it’s easy when you know the answer_. That’s exactly why you [hire
consultants](/consultancy/).