Skip to main content

Font Display.

Performance Asset Optimization

font-display: swap prevents invisible text while custom fonts load

What does this check test?

This check verifies that custom web fonts use the `font-display` CSS descriptor to control how text is rendered while the font is loading. Without `font-display`, many browsers hide text entirely until the custom font downloads (known as FOIT — Flash of Invisible Text), which can last 3+ seconds on slow connections. The `font-display: swap` value tells the browser to immediately show text in a fallback font and swap to the custom font when it's ready. Other values include `optional` (best for performance — uses the font only if it loads very quickly), `fallback` (short invisible period, then fallback), and `block` (hides text for up to 3 seconds).

Why does it matter?

Invisible text during font loading is one of the most jarring user experiences — visitors see a fully laid out page with no readable content. This directly impacts FCP (no text content is painted until the font loads) and can affect LCP if the largest element is text. Users on slow connections may wait several seconds before any text appears, leading to confusion and abandonment. Using `font-display: swap` ensures text is always visible, even if it briefly appears in a fallback font before the custom font loads. This is a simple CSS change with a major impact on perceived performance.

Who is affected?

Every site using custom web fonts (Google Fonts, Adobe Fonts, self-hosted fonts) is affected. Sites with multiple custom font families, sites using fonts loaded from slow third-party origins, and sites that use custom fonts for body text (not just headings) are most impacted. Sites targeting users on slow connections where font downloads may take several seconds see the worst effects.

Where does this apply?

Check `@font-face` declarations in your CSS for the `font-display` property. Google Fonts URLs should include the `&display=swap` parameter. Inspect the Fonts tab in Chrome DevTools (under the Application panel) to see which fonts are loaded and their status. Lighthouse flags `@font-face` declarations that are missing the `font-display` descriptor.

How to fix it

Add `font-display: swap` (or `optional` for best performance) to all `@font-face` declarations. Declare font-display and preload the critical font:
css
@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: swap;
}
html
<link rel="preload" href="/fonts/custom.woff2" as="font" type="font/woff2" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet" />
Match fallback font metrics to minimize swap shift:
css
@font-face {
  font-family: 'CustomFont-Fallback';
  src: local('Arial');
  size-adjust: 105%;
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
}
For even better performance, use `font-display: optional` — this shows the fallback font permanently if the custom font does not load within 100ms, eliminating all layout shifts from font swapping.

References

AppVet checks Font Display automatically

Run a free performance scan and get a full report with actionable fixes, including a Fix with AI prompt you can paste into any coding tool.

Run Audit