All guides · Performance

Web Fonts: Keep Text Visible While Fonts Load

Custom web fonts are separate files that the browser only discovers once it has the CSS that uses them. Until they arrive, the browser has to decide what to do with the text: hide it, or show it in a fallback font and swap later. By default many browsers hide it for up to a few seconds, which on a slow connection means visitors see a page with empty spaces where the headings and paragraphs should be.

Why it matters

Invisible text delays the moment a page becomes readable, and when the largest element on screen is text, it delays Largest Contentful Paint too. Fonts that arrive late and swap in a very different fallback can also shift the layout, which counts toward Cumulative Layout Shift.

font-display

The font-display descriptor in each @font-face rule controls this behaviour:

Value What happens
block text is hidden for a short period, then shown in the fallback until the font loads
swap text shows in the fallback immediately and switches when the font arrives
fallback a very short hidden period, then the fallback; the font is used only if it arrives soon
optional like fallback, but the browser may skip the font entirely on slow connections
auto the browser decides, which usually means block

swap is the common choice for brand and body fonts. optional avoids layout shifts completely and suits body text where the fallback is acceptable.

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

How to fix

Google Fonts

Add display=swap to the stylesheet URL. Google then includes font-display: swap in every @font-face rule it returns:

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

Self-host your fonts

Serving fonts from your own domain avoids connecting to extra origins and gives you full control over font-display and caching. Most open-source fonts, including those on Google Fonts, allow self-hosting; check the licence for commercial fonts.

Preload the main font

Preloading lets the browser fetch a font before it has parsed the CSS that needs it. Preload only the one or two files used on the first screen; preloading everything competes with more important files. The crossorigin attribute is required for fonts, even on your own domain:

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

Use WOFF2 and subset

WOFF2 is supported by all modern browsers and is the most compact font format, so older formats like TTF, EOT or SVG fonts are no longer needed. If your site uses one script, such as Latin, serve a subset that contains only those characters. unicode-range in @font-face lets the browser download a subset only when the page uses characters from it. A variable font can replace several weight files with one.

WordPress

Many themes load Google Fonts from their options; look for a setting to self-host them or to set the display behaviour. Recent WordPress versions include a Font Library for block themes that stores fonts on your own site. Some optimisation plugins can also add font-display: swap to font rules they find.

Fonts in CSS you don’t control

If a third-party stylesheet loads a font without font-display, you can’t change its rules. Ask whether the provider offers a display option, or self-host the font instead.

How PerfoMetrix checks this

We read Lighthouse’s font display audit (font-display-insight) from the PageSpeed Insights run we already make (mobile, simulated device). If Lighthouse rates it 0.9 or higher, or the page uses no web fonts, the check passes; otherwise it needs attention. We show Lighthouse’s estimate, such as “Est savings of 80 ms”, and the first five font files it lists.

This check is shown but doesn’t count toward the performance score: its effect is already measured by FCP and LCP, which are scored. No extra requests are made to your site.

Learn more

Last updated October 28, 2026