Font Converter

Font Fallback Chains: Building Robust font-family Stacks

A practical guide to constructing font-family stacks that survive any condition: custom font failures, character gaps, and slow connections — without layout shift.

TL;DR

  • • Order your stack: custom web font → similar system font → cross-platform safe font → generic family
  • • Use size-adjust, ascent-override, descent-override, and line-gap-override to match fallback metrics exactly
  • • Use system-ui when you want a native OS feel with zero load time
  • • Metric-matched fallbacks eliminate Cumulative Layout Shift (CLS) during font swap

Share this page to:

Sarah Mitchell

Written & Verified by

Sarah Mitchell

Product Designer, Font Specialist

What is a Font Fallback Chain?

The CSS font-family property accepts a comma-separated list of font names. This list is a fallback chain — an ordered sequence of fonts the browser evaluates left to right. The browser renders each character using the first font in the list that both contains the character and is available on the user's device.

Fallbacks activate in three scenarios: the custom web font fails to download, the font downloads but lacks a specific character (for example, a Greek letter in a Latin-only font), or the font has not yet loaded and the browser falls back to a system font while waiting. Because browsers operate character by character — not word by word — a single line of text can draw glyphs from multiple fonts simultaneously.

/* The browser reads this list left to right */
font-family:
  'Inter',          /* 1st: preferred custom web font */
  'Helvetica Neue', /* 2nd: similar macOS system font */
  Arial,            /* 3rd: cross-platform fallback   */
  sans-serif;       /* 4th: generic family             */

Without a well-designed fallback chain, a font failure means the browser falls back to its default serif font — Times New Roman on most systems — even if your design calls for a clean sans-serif. The chain is your insurance policy: it controls exactly which font users see when your first choice is unavailable.

System Font Inventory by Operating System

Knowing which fonts are pre-installed on each platform lets you craft accurate fallbacks. The table below lists the primary system fonts across major operating systems for five script categories.

OSSerifSans-SerifMonospaceCJKArabic / Indic
macOS / iOSGeorgia, Times New RomanSan Francisco (SF Pro), Helvetica NeueSF Mono, Menlo, MonacoHiragino Sans, PingFang SC/TC, Apple SD Gothic NeoGeeza Pro (Arabic), Kohinoor Devanagari
Windows 11Georgia, Times New Roman, CambriaSegoe UI, Segoe UI Variable, CalibriCascadia Code, Consolas, Courier NewMicrosoft YaHei (SC), Microsoft JhengHei (TC), Meiryo, Malgun GothicSegoe UI Historic (Arabic), Mangal (Devanagari)
Android 14Noto SerifRoboto, Roboto FlexRoboto MonoNoto Sans CJK SC/TC/JP/KRNoto Naskh Arabic, Noto Sans Devanagari
Linux (Ubuntu)DejaVu Serif, Liberation SerifUbuntu, DejaVu Sans, Liberation SansUbuntu Mono, DejaVu Sans MonoWenQuanYi Micro Hei, IPAGothicLohit Devanagari, Amiri (Arabic)

Note: San Francisco is not accessible by font name — use -apple-system or system-ui to access it on Apple devices.

Building Effective Fallback Stacks

The goal is to degrade gracefully, maintaining visual similarity at each level. A four-tier approach works for most cases.

1
Primary

Your custom web font — loaded via @font-face

2
System Similar

Platform font that closely matches your custom font

3
Cross-Platform

A font present everywhere (Arial, Georgia)

4
Generic

Final safety net: sans-serif, serif, monospace

Latin Script Stack (Inter-based)

/* Inter + system fallbacks */
font-family:
  'Inter',           /* Custom: Google Fonts / self-hosted */
  'Helvetica Neue',  /* macOS similarity fallback          */
  Arial,             /* Windows / cross-platform           */
  sans-serif;        /* Generic safety net                 */

CJK-Ready Stack (Japanese priority)

/* Supports Latin + Japanese + Chinese fallback */
font-family:
  'Noto Sans JP',        /* Custom CJK web font             */
  'Hiragino Sans',       /* macOS Japanese system font      */
  'Yu Gothic',           /* Windows Japanese system font    */
  'Meiryo',              /* Older Windows Japanese          */
  'Microsoft YaHei',     /* Windows Chinese — CJK overlap   */
  sans-serif;

Arabic / RTL Stack

/* Arabic text with system fallbacks */
font-family:
  'IBM Plex Arabic',   /* Custom Arabic web font           */
  'Geeza Pro',         /* macOS / iOS system Arabic font   */
  'Arabic Typesetting',/* Windows Arabic system font       */
  'Noto Naskh Arabic', /* Android / Linux fallback         */
  sans-serif;

Mixed-Script Stack (global audience)

/* Latin primary, wide script coverage in fallbacks */
font-family:
  'Inter',
  'Noto Sans',          /* covers 1000+ scripts via subset  */
  'Hiragino Sans',      /* macOS Japanese                   */
  'Noto Sans CJK SC',   /* Android Simplified Chinese       */
  'Microsoft YaHei',    /* Windows Simplified Chinese       */
  'Geeza Pro',          /* macOS Arabic                     */
  'Noto Naskh Arabic',  /* Android Arabic                   */
  sans-serif;

CSS Font Metric Override Properties

Every font carries internal metrics that determine how much vertical space it occupies: the ascent (height above the baseline), descent (depth below the baseline), and line gap (extra spacing between lines). When the browser swaps from a fallback font to your web font, differences in these metrics cause elements to shift — contributing to Cumulative Layout Shift (CLS).

CSS provides four @font-face descriptors to override these metrics on a fallback font, forcing it to match the dimensions of your web font:

size-adjust

Scales the entire glyph and metrics of the fallback font by a percentage. If your web font renders slightly smaller than Arial at the same font-size, set size-adjust: 105% to expand Arial to match.

size-adjust: 105%;   /* Scale fallback up 5% */
size-adjust: 92%;    /* Scale fallback down 8% */

ascent-override

Sets the ascent metric as a percentage of the font-size. The ascent determines how far above the baseline the tallest glyphs reach (capitals, ascenders like 'h' and 'l'). Matching this prevents the first line from jumping vertically on swap.

ascent-override: 90%;   /* Most web fonts: 85–100% */

descent-override

Sets the descent metric — how far below the baseline descenders (g, j, p, q, y) extend. This controls the bottom boundary of each line box.

descent-override: 22%;  /* Typical range: 15–35% */

line-gap-override

Sets the line gap metric — the recommended extra space between lines built into the font itself (separate from CSS line-height). Most modern web fonts set this to 0, relying on CSS instead.

line-gap-override: 0%;   /* Match web fonts with no built-in gap */

Complete Metric-Matched Fallback @font-face

The pattern is to create a new virtual font name that maps to a local system font, then apply all four overrides to match your web font's metrics:

/* Step 1: Your web font */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter-variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}

/* Step 2: Metric-matched fallback that mimics Inter's dimensions */
@font-face {
  font-family: 'Inter-Fallback';
  src: local('Arial');        /* Use system Arial, no download */
  size-adjust: 107%;          /* Inter is slightly narrower than Arial */
  ascent-override: 90%;       /* Inter ascent metric            */
  descent-override: 22.43%;   /* Inter descent metric           */
  line-gap-override: 0%;      /* Inter has no built-in line gap */
}

/* Step 3: Reference both in your font stack */
body {
  font-family: 'Inter', 'Inter-Fallback', sans-serif;
}

How to find exact values: Use the Perfect Font Fallback tool or the next/font package (which computes these values automatically). You can also extract metrics from the font file using tools like fonttools and the formula: metric / unitsPerEm * 100%.

Preventing Cumulative Layout Shift (CLS)

Font-related CLS occurs because different fonts occupy different amounts of space at the same CSS font-size. When the browser renders your page initially with a fallback font and then swaps to the web font, every text element whose dimensions change causes layout shift — elements below the text jump, images reflow, and users lose their scroll position.

What causes the shift

Before (no metric matching)

Fallback font (Arial, 16px) takes 24px of vertical space per line. Web font (Inter, 16px) takes 21px. Result: a 400-word article shrinks by ~12px on font swap, pushing all subsequent content upward.

/* No metric matching — causes CLS */
font-family: 'Inter', Arial, sans-serif;

After (metric-matched fallback)

The Inter-Fallback @font-face overrides Arial's metrics to match Inter exactly. Both occupy 21px per line. Font swap is invisible — no layout shift, CLS score near zero.

/* Metric-matched — zero CLS */
font-family: 'Inter', 'Inter-Fallback', sans-serif;

Calculation approach

To calculate the correct size-adjust value, find the ratio of your web font's x-height to the fallback font's x-height. Then invert it:

/* Formula:
   size-adjust = (webFont.xHeight / fallbackFont.xHeight) * 100%

   Example: Inter x-height = 0.527em, Arial x-height = 0.495em
   size-adjust = (0.527 / 0.495) * 100 = 106.46% ≈ 107%
*/

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

The next/font module in Next.js 13+ computes and injects these values automatically. The open-source Fontaine package does the same for Vite/Nuxt projects.

Generic Font Families

CSS defines ten generic font families. The browser maps each to the best available installed font on the current platform. These should always be the final entry in your fallback chain — they guarantee some font is always used, even if nothing else in the list is available.

Generic FamilymacOSWindowsAndroidUse Case
system-uiSan Francisco (SF Pro)Segoe UI VariableRobotoNative app feel, UI text
ui-serifNew YorkCambriaNoto SerifSystem serif for reading
ui-sans-serifSan FranciscoSegoe UIRobotoSystem sans for body text
ui-monospaceSF MonoCascadia CodeRoboto MonoCode blocks, terminals
ui-roundedSF Pro Rounded(no match)(no match)Friendly / playful UI (Apple only)
sans-serifHelveticaArialRobotoUniversal last resort
serifTimes New RomanTimes New RomanNoto SerifSerif last resort
monospaceCourier NewCourier NewDroid Sans MonoCode, terminal last resort
emojiApple Color EmojiSegoe UI EmojiNoto Color EmojiEmoji character rendering
mathSTIX Two MathCambria MathNoto Sans MathMathematical notation

Tip: The difference between system-ui and sans-serif is significant. system-ui maps to the OS UI font (San Francisco, Segoe UI Variable, Roboto), while sans-serif may map to an older system default like Helvetica or Arial. For UI-style designs, prefer system-ui.

Ready-to-Use Font Stacks

These stacks are copy-paste ready. Each covers the most common failure scenarios for its intended use case. Replace the first value with your own custom web font as needed.

Modern Sans-Serif
font-family:
  'Inter',
  -apple-system,
  BlinkMacSystemFont,
  'Segoe UI',
  Roboto,
  'Helvetica Neue',
  Arial,
  'Noto Sans',
  sans-serif,
  'Apple Color Emoji',
  'Segoe UI Emoji';

Industry standard. Covers macOS (-apple-system), Chrome on macOS (BlinkMacSystemFont), Windows (Segoe UI), Android (Roboto), and emoji on all platforms.

Classic Serif
font-family:
  'Lora',
  'Palatino Linotype',
  'Book Antiqua',
  Palatino,
  Georgia,
  'Times New Roman',
  serif;

Lora as the custom serif, Palatino variants on macOS/Windows, Georgia as the universal fallback, Times New Roman as final serif anchor.

Monospace / Code
font-family:
  'JetBrains Mono',
  'Fira Code',
  'Cascadia Code',
  'SF Mono',
  'Menlo',
  'Consolas',
  'Liberation Mono',
  'Courier New',
  monospace;

JetBrains Mono and Fira Code as custom options, Cascadia Code for Windows 11, SF Mono/Menlo for macOS, Consolas for older Windows, Liberation Mono for Linux.

CJK-Ready
/* For Simplified Chinese + Latin sites */
font-family:
  'PingFang SC',        /* macOS / iOS */
  'Hiragino Sans GB',   /* macOS legacy */
  'Microsoft YaHei',    /* Windows */
  'Noto Sans SC',       /* Android / Linux */
  'WenQuanYi Micro Hei',/* Linux */
  sans-serif;

Use :lang(zh-Hans) selector to apply this only to Simplified Chinese text elements, keeping Latin text on your primary stack.

RTL-Ready (Arabic)
/* For Arabic / RTL sites */
font-family:
  'Noto Naskh Arabic',  /* Google Fonts, excellent coverage */
  'Cairo',              /* Alternative: modern geometric    */
  'Geeza Pro',          /* macOS / iOS system Arabic        */
  'Arabic Typesetting', /* Windows system Arabic            */
  'Amiri',              /* Linux / serif Arabic fallback    */
  sans-serif;

Always pair with direction: rtl and text-align: right (or text-align: start with logical properties).

System Native
/* Native OS feel, zero load time */
font-family:
  system-ui,
  -apple-system,
  BlinkMacSystemFont,
  'Segoe UI Variable',
  'Segoe UI',
  sans-serif;

No web font loading at all. Ideal for dashboards, admin UIs, and performance-critical pages where brand font is not required. Zero CLS, zero font load time.

Font Fallback Chains FAQs

Common questions about building robust font-family stacks

Sarah Mitchell

Written & Verified by

Sarah Mitchell

Product Designer, Font Specialist

Related Resources

Generate Your Font Stack CSS

Use our CSS Generator to build @font-face declarations with size-adjust and metric overrides calculated automatically.

Open CSS Generator