font-display and web font loading
By Christian Schreiber ยท Updated
The Lighthouse finding Ensure text remains visible during webfont load appears when a page uses a web font without telling the browser what to show while the font file is still downloading. By default, most browsers hide the text for up to three seconds and then fall back, which means a visitor on a slow connection stares at empty space where the headline should be. The font-display descriptor fixes that in one line. Done carelessly, though, the fix trades invisible text for a visible jump when the real font arrives. This guide covers the values, the preload and the sizing trick that avoids both problems.
What happens when a web font loads
The browser discovers the font file only after it has parsed the CSS that references it, so the font is always one of the last critical resources to arrive. While it waits, the browser has to decide: render the text in a fallback font (and re-render later), or render nothing. font-display controls that decision for each @font-face rule:
| Value | Block period | Swap period | Effect |
|---|---|---|---|
auto | browser default | browser default | usually like block: text hidden up to three seconds |
block | short (about three seconds) | infinite | text hidden, then swapped whenever the font arrives |
swap | none | infinite | fallback text immediately, swapped whenever the font arrives |
fallback | very short (about 100 ms) | short (about three seconds) | fallback text almost immediately; late fonts are not swapped in |
optional | very short | none | the font is used only if it is already available; otherwise the fallback stays |
Lighthouse flags @font-face rules that use auto or block, or no descriptor at all. swap, fallback and optional all pass.
Which value to use
swapis the usual recommendation and what most font services default to. Text is readable at once. The cost is a visible swap when the font arrives, which counts as a layout shift if the fallback and the web font differ in size.optionalis the strictest choice for performance: no swap, no shift, and the font is cached for the next page view. Body text on content-heavy sites is a good fit. The brand font may be missing on the very first visit.fallbacksits in between and suits secondary fonts that are nice to have but not essential.blockis defensible only for icon fonts, where fallback glyphs would show meaningless characters. Even there, inline SVG is the better solution.
How to fix the finding
1. Self-hosted fonts: add the descriptor
@font-face {
font-family: "Inter";
src: url("/fonts/inter-var.woff2") format("woff2");
font-weight: 100 900;
font-display: swap;
}
Use WOFF2 only; every current browser supports it and it is the smallest format. A variable font replaces several weight files with one.
2. Google Fonts: add the display parameter
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
Without &display=swap the generated CSS uses the default and Lighthouse reports the finding. Better still, download the font files and self-host them: that removes two external origins from the critical path and gives you control over caching. The preconnect guide covers the interim option of preconnecting to fonts.gstatic.com.
3. Preload the fonts used above the fold
<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin>
Preloading starts the download before the CSS is parsed, which shortens the swap period and often means the font arrives before the first paint. Preload only the one or two files the first screen needs; each preload competes with the LCP image.
4. Match the fallback font to avoid layout shifts
The swap itself is not the problem; the size difference between fallback and web font is. If the fallback renders wider or taller, every line wraps differently and the whole page jumps, which shows up in Cumulative Layout Shift. The size-adjust, ascent-override, descent-override and line-gap-override descriptors tune a local fallback to the same metrics:
@font-face {
font-family: "Inter Fallback";
src: local("Arial");
size-adjust: 107%;
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
}
body { font-family: "Inter", "Inter Fallback", sans-serif; }
The right percentages depend on the font pair. Tools that compute them from the font files exist, and frameworks such as Next.js generate this block automatically with next/font.
5. Subset and limit the fonts
A font family with four weights in two styles is eight files. Most pages need two. Subset to the character ranges you use (Latin only, for example) and use a variable font where available. Fewer and smaller files mean a shorter swap period, whatever the display value.
Platform notes
- WordPress: block themes bundle fonts locally and set
font-display: swap. Themes and plugins that load Google Fonts through their own stylesheet are the usual source of the finding; many have a "font display" or "local fonts" option. - Shopify: fonts from the Shopify font library are served with
font-display: swapby the platform. Findings here typically come from apps or custom fonts added to the theme. - Next.js:
next/fontself-hosts, preloads, setsfont-displayand generates a size-adjusted fallback. A manual@font-facenext to it is almost always a leftover.
Frequently asked questions
Is font-display: swap always the best choice?
It is the safe default for readability. For body text on content sites, optional avoids the swap and any layout shift at the cost of possibly showing the fallback on the first visit.
Does font-display: swap cause layout shifts?
It can, when the fallback font has different metrics. A size-adjusted fallback font, defined with size-adjust and the override descriptors, removes the shift.
Why does the finding still appear after I added display=swap to Google Fonts?
Another stylesheet is probably loading fonts without it, often from a theme, a plugin or an embedded widget. The finding lists the exact font URLs.
Should I preload all my fonts?
No. Preload the one or two files used above the fold. More preloads delay the LCP image and the CSS.
Thresholds and sources
Sources:
- Lighthouse: Ensure text remains visible during webfont load
- web.dev: Best practices for fonts
- web.dev: Optimize CLS
All sources retrieved on October 9, 2026. Thresholds and documentation change; the linked page is authoritative.
Test your site
Run a free scan to see whether this applies to your pages, on mobile and desktop, with lab and field data side by side.
Run a free testA free account saves your tests and shows how your values change from one test to the next. Daily monitoring with field data and alerts starts with the Solo plan.