design hubs
On this page
Web Typography
5 min read

Font Stacks and Fallbacks

A font stack is the ordered list of typefaces the browser tries in sequence. Designing the fallback is as important as choosing the primary web font.

Every font-family declaration is a stack. The browser tries each typeface in order and uses the first one available. On a system where your web font fails to load — a slow connection, a blocked request, a cached font that has expired — the fallback typeface is what the user reads. Designing the fallback is not an afterthought. It is a parallel typographic decision that affects every user during the loading window and some users permanently.

The anatomy of a font stack

font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

The stack reads left to right: Inter is the preferred web font; -apple-system and BlinkMacSystemFont are the system UI fonts on macOS/iOS and older macOS/Chrome respectively; Segoe UI is the Windows system font; Roboto is the Android system font; Helvetica and Arial are near-universal sans-serif fallbacks; sans-serif is the generic family, guaranteed to exist on every system. Each level is a graceful step down: from the preferred web font through platform UI fonts to the universal fallback.

System font stacks

A system font stack uses no web fonts at all — it renders in the platform’s native UI font on every device. The result loads instantly (no network request), matches the platform aesthetic, and has no FOUT or FOIT. For interfaces where performance and native feel matter more than typographic precision — dashboards, admin panels, developer tools — a system font stack is a legitimate and often better choice than a web font.

/* System UI font stack */
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
  Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', Arial, sans-serif;

/* Or using the CSS system-ui keyword (all modern browsers) */
font-family: system-ui, sans-serif;

system-ui is the standardised CSS keyword that resolves to the platform’s default UI font: San Francisco on macOS/iOS, Segoe UI on Windows, Roboto on Android. It requires no fallback list for modern browsers.

FOUT and FOIT: the swap problem

Web fonts create two failure modes during loading. FOUT (Flash of Unstyled Text) renders text in the fallback font and then swaps to the web font when it loads — the user sees a visible reflow. FOIT (Flash of Invisible Text) hides text until the web font loads — the user sees blank space.

The font-display descriptor controls this behaviour:

@font-face {
  font-family: 'Inter';
  src: url('Inter-Variable.woff2') format('woff2');
  font-display: swap;  /* FOUT: show fallback immediately, swap on load */
}

font-display: swap is the right choice for body text — text is always visible. font-display: optional renders the web font only if it loads within ~100ms (first visit from cache on repeat loads); otherwise the system font is used for the duration of the page. optional eliminates layout shift entirely but sacrifices the web font on slow connections.

Matching fallback metrics

The layout shift caused by FOUT is proportional to the difference in metrics between the web font and its fallback. A web font with a tall x-height and tight line spacing swapping to a fallback with a low x-height produces dramatic reflow. The CSS size-adjust, ascent-override, descent-override, and line-gap-override descriptors allow precise metric adjustment on the fallback font within an @font-face block, so the fallback renders at the same visual size as the web font:

@font-face {
  font-family: 'Inter-fallback';
  src: local('Arial');
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
  size-adjust: 107%;
}

body {
  font-family: 'Inter', 'Inter-fallback', sans-serif;
}

The values for your specific web font can be calculated using tools like fontaine or by inspecting font metrics with browser devtools. When the fallback is correctly adjusted, FOUT produces no visible reflow — the text occupies the same space before and after the swap. This is the gold standard for web font loading.

One stack per weight and style

The fallback stack should be defined for every weight and style combination you use, not just the regular weight. If you use font-weight: 700 for headings, the @font-face declaration for the bold weight needs its own font-display and, ideally, its own metric-adjusted fallback. Without this, the browser synthesises bold from the regular weight (thicker strokes generated algorithmically), which looks noticeably different from the genuine bold — particularly at display sizes.

@font-face {
  font-family: 'Inter';
  src: url('Inter-Bold.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}

Choosing fallbacks deliberately

The fallback typeface should be chosen for metric similarity to the primary, not for availability alone. Arial is universally available but has different proportions from most contemporary sans-serifs. Georgia is widely available but is a serif — an inappropriate fallback for a sans-serif primary.

Measure the x-height ratio (x-height divided by cap height) and the average glyph width of your web font and compare it to potential fallbacks. A closer match means less visible reflow. For variable fonts with unusual proportions, Georgia might be a closer match than Arial for a specific weight — metrics, not family type, should guide the choice.

Testing without the web font

The practical test for fallback stack quality is disabling web fonts entirely. In browser devtools, under the Network panel, block requests matching the font file URL and reload the page. What you see is what users on slow connections or blocked requests experience. If the fallback produces a dramatically different reading experience — different line breaks, different paragraph lengths, different visual hierarchy — the fallback stack needs work.

The metric override approach, when applied correctly, produces a fallback that is nearly indistinguishable in layout from the web font. Users on slow connections experience the correct layout with the system font; the web font swap is invisible when it arrives.

Keyboard shortcuts

Show shortcuts
?
Search
CtrlK
Previous article
Next article
Close
Esc