Reference guide · performance · Published 2026-08-16 · 4 min read

Font loading best practice

Font loading best practice: font-display swap, preload the LCP font, self-host versus CDN, and subsetting to cut layout shift and LCP.

Flat editorial illustration showing a speedometer gauge with a rising needle, clean tick marks and small trailing dots.
Illustration: this article at a glance.

Why fonts sit on the critical path

A web font is a file the browser only needs if a text element uses that family. But while the stylesheet that loads it is usually render-blocking, the font file itself is a late request launched after CSS is parsed. That makes fonts a frequent LCP contribution: the hero heading in the brand font cannot paint until the font file arrives, and a slow font origin can hold the hero hostage.

Two visible symptoms come from the same root: FOIT (invisible text while the font loads, the browser holds the text invisible) and layout shift when the font swaps in at a different width than the fallback (metrics fallback). Both are avoidable with the same tool: the CSS font-display descriptor.

font-display swap

@font-face accepts a font-display descriptor. The values produce different fallback behavior:

ValueBehavior during loadUse case
autoBrowser decides; often FOITThe old default, avoid for body text
blockInvisible text for a short window (max a few seconds), then swapDisplay type where the first paint must match the family
swapFallback text immediately, swap when the font arrivesThe safe default for most sites
fallbackVery short FOIT (roughly 100 ms), then fallback; font swap only within a short capBody text, tighter consistency
optionalUses fallback unless the font is already cached or arrives extremely fastDecorative text, avoids reflow entirely

The practical rule: body and general text get swap or fallback; display text that must not reflow (e.g. a big headline) can use block, but the same text should then be measured to avoid layout shift.

With swap, measure the LCP against a simulated slow font to see if the fallback appears first. If the fallback is close in width (a size-adjust on the @font-face, or the new-style fallback metrics), the shift stays under control.

The three rules that win

  1. Preload the LCP font. Add <link rel="preload" as="font"> for the exact font-face used by the largest heading, with crossorigin. This moves the download start before CSS parsing. The page-speed preload article explains the sibling pattern for the LCP image.
  2. Serve the subset the text uses. If the page only uses Latin, shipping a full-font + fallback wastes bytes and arrival time on anything heavier. Use Unicode-range subsetting (fonttools / Google Fonts "CSS2 API" splits) and keep the LCP font-file weight under ~30-60 KB.
  3. Self-host and control the TTFB for the font request. The CDN for static assets article covers the delivery side; LCP is sensitive to the font *first byte*, so preconnect to the font origin (self-hosted or third-party) or self-host critically in the preconnect guide.

The load order

Practical load order for fonts:

  1. The stylesheet (font-family declarations) is render-blocking, load it with the CSS.
  2. Add preload for the two files that matter (hero font-face via as="font", plus imagesrcset when defined, the WebP/AVIF compare has the image pairs).
  3. The rest of the family loads afterward via normal CSS; do not preload every weight.

There is one more scaling rule: do not load more than two families. One for headings, one for body, fallbacks for both. A page with six font-faces is a page that shifted multiple times.

Detection and measurement

Test with the DevTools Network panel filtered to font and check font-display timing in the Coverage tab. The two numbers to watch are:

Prevention

Decide the font-display strategy per family (body vs display), preload only the LCP font, and keep the family count small. Recheck after any theme or builder update, because the pattern "now 5 font files load" typically outweighs every other font decision. The web performance audit lives in the same family and will want to see the font request count on the LCP chart, so keep it low.

Need a website built, fixed, optimised, migrated or replaced?

This technical resource is written by CSMBAC, a small design and development studio. If you would rather hand the problem to a professional, the website service page explains how we build enquiry-ready websites.

Explore website services