Skip to content
Performance

Font Loading Strategies

Load web fonts efficiently without blocking rendering or causing layout shifts.

stellae.design

7 min read

Introduction

Web fonts make your site look great but can seriously hurt performance if loaded incorrectly. Flash of Invisible Text (FOIT) makes content unreadable while fonts download. Flash of Unstyled Text (FOUT) causes jarring layout shifts.

The key challenge is balancing visual design with performance. Modern CSS and browser APIs give us excellent tools to achieve both fast loading and beautiful typography.

This guide covers every technique from basic font-display to advanced strategies like subsetting and variable fonts.


Key Concepts

font-display Property

css
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  font-display: swap; /* Show fallback immediately, swap when loaded */
}

Preloading Critical Fonts

html
<link rel="preload" href="/fonts/inter-regular.woff2" as="font" type="font/woff2" crossorigin>
<!-- crossorigin is required even for same-origin fonts! -->

Font Subsetting

bash
pyftsubset Inter-Regular.ttf \
  --output-file=Inter-Regular-Latin.woff2 \
  --flavor=woff2 \
  --unicodes='U+0000-00FF,U+0131,U+0152-0153'

Practical Examples

1. Optimal Google Fonts Loading

html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">

2. Variable Fonts

css
@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-Variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}

3. Fallback Font Matching

css
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  font-display: swap;
  ascent-override: 90%;
  descent-override: 22%;
  size-adjust: 107%;
}

Best Practices

  • ✅ Use font-display: swap for body text, optional for non-critical fonts
  • ✅ Preload critical fonts (1-2 max) used above the fold
  • ✅ Self-host fonts for better performance and privacy
  • ✅ Use variable fonts to reduce total font file downloads
  • ✅ Subset fonts to include only needed character sets
  • ❌ Don't preload more than 2-3 font files
  • ❌ Don't use font-display: block — it causes FOIT

Common Pitfalls

  • 🚫 Forgetting crossorigin on preload — font preloads without it are fetched twice
  • 🚫 Loading too many font weights — use variable fonts or limit to 2-3
  • 🚫 Not matching fallback metrics — causes CLS when custom font swaps in
  • 🚫 Using Google Fonts without preconnect — adds 100-300ms

Performanceperformance

Was this article helpful?