Featured image of post Optimizing Web Font Loading: Preventing FOUT and FOIT Featured image of post Optimizing Web Font Loading: Preventing FOUT and FOIT

Optimizing Web Font Loading: Preventing FOUT and FOIT

Ensure font rendering stability using font-display and preload tactics, preventing layout shifts.

Introduction

Web fonts enhance design but come at a cost. While a custom font loads, browsers must decide: show invisible text (FOIT — Flash of Invisible Text) or show a fallback font (FOUT — Flash of Unstyled Text). Either choice impacts CLS (Cumulative Layout Shift) and user experience. This article covers strategies to load fonts reliably while minimizing layout shifts.


The font-display Descriptor

The font-display property in @font-face controls how a font is displayed during loading:

@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont.woff2') format('woff2');
  font-display: swap;
}
ValueBehaviorUse Case
autoBrowser default (usually FOIT)Default
blockInvisible text up to ~3s, then swapShort block period
swapFallback font immediately, swap when readyMaximum readability
fallbackInvisible text ~100ms, fallback ~3s, then swapBalance
optionalShort block, optional downloadSlow connections

swap is the most common choice — it shows fallback text immediately, then swaps when the custom font loads, completely eliminating FOIT.


Preloading Critical Fonts

Use <link rel="preload"> in the <head> to start font downloads early:

<link rel="preload" href="/fonts/myfont.woff2" as="font" type="font/woff2" crossorigin>

The crossorigin attribute is required for fonts loaded from a different origin, even same-origin fonts served via CDN. Without it, the preload is ignored.


Self-Hosting vs. CDN

ApproachProsCons
Self-hostFull control, no extra DNS lookup, cache controlBandwidth cost
Google Fonts / CDNFast edge delivery, automatic subsettingExtra DNS + TLS handshake

For critical fonts, self-hosting often performs better because it eliminates the extra connection to the font provider. Use preconnect if you must use a third-party font service:

<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>

Font Subsetting

Including every glyph in a font file wastes bandwidth. Subsetting removes unused characters:

# Using pyftsubset (fonttools)
pyftsubset Roboto-Regular.ttf --unicodes="U+0020-007E,U+00A0-00FF"

Most CDN font services do this automatically. For self-hosted fonts, generate subsets for each language you support. Tools like glyphhanger or fonttools can output files as small as 10-20 KB instead of 100+ KB.


WOFF2: The Modern Standard

WOFF2 (Web Open Font Format 2) offers 30-50% better compression than WOFF:

@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont.woff2') format('woff2'),
       url('/fonts/myfont.woff') format('woff'); /* fallback */
}

All modern browsers support WOFF2. Use it as the primary format with WOFF as a fallback.


Preventing Layout Shift with size-adjust

The size-adjust descriptor in @font-face lets you normalize metrics so the fallback and custom fonts occupy the same space:

@font-face {
  font-family: 'Fallback';
  src: local('Arial');
  size-adjust: 95%;
  ascent-override: 85%;
  descent-override: 20%;
}

Use tools like the size-adjust calculator (Chrome DevTools > Rendering > Font Size Adjust) to find the correct values. This dramatically reduces CLS when the font swaps.


Complete Optimization Recipe

<head>
  <!-- Preconnect to font origin -->
  <link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
  <link rel="dns-prefetch" href="https://fonts.googleapis.com">

  <!-- Preload the main font -->
  <link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
</head>
@font-face {
  font-family: 'Main';
  src: url('/fonts/main.woff2') format('woff2');
  font-display: swap;
}

body {
  font-family: 'Main', 'Fallback', sans-serif;
}

Conclusion

Optimizing web fonts requires a multi-layered approach: use font-display: swap to prevent FOIT, preload critical fonts, subset your files, serve WOFF2, and apply size-adjust to minimize CLS. These techniques together ensure fast, stable, and beautiful typography.