Ensure Text Stays Visible During Webfont Load (font-display): How to Fix It
- February 17, 2021
- Performance, Fonts

What this check flags
This audit fires when your webfonts load without a font-display strategy, so the browser hides your text until the font file arrives, a flash of invisible text (FOIT). Visitors stare at a blank block of nothing while the font downloads, and if that font is your LCP element, your Largest Contentful Paint waits on it too. A late font swap can also shove text around and spike Cumulative Layout Shift.
The real example, and the fix
The problem is the default. A plain @font-face block behaves like font-display: auto, which most browsers treat as a block period of up to 3 seconds of invisible text:
/* FOIT: text is invisible while Inter downloads */
@font-face{ font-display:swap;
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
}The fix is one line. Add font-display: swap so the browser paints text immediately in a fallback font, then swaps to your webfont when it lands:
@font-face{
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
font-display: swap; /* text visible instantly, swaps when ready */
}If you load fonts from Google Fonts by URL, add &display=swap to the request and the generated @font-face rules include it for you:
<link href="https://fonts.googleapis.com/css2?family=Inter&display=swap" rel="stylesheet">Two more moves kill the leftover shift. Preload the font so it starts downloading early, and use size-adjust / the @font-face metric overrides so your fallback occupies almost the same space as the real font, making the swap nearly invisible:
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
@font-face{ font-display:swap;
font-family: 'Inter-fallback';
src: local('Arial');
size-adjust: 107%;
ascent-override: 90%;
}Which font-display value to pick
font-display takes five values, and the right one depends on whether you care more about your brand font showing up or about text never being invisible:
| Value | Block period (invisible) | Swap period | Use it when |
|---|---|---|---|
auto | ~3s (browser default) | varies | Never, on purpose, this is the failing state |
block | ~3s | infinite | Icon fonts where a fallback glyph would be nonsense |
swap | 0s | infinite | Body and heading text, the safe default |
fallback | ~100ms | ~3s | You want the webfont but will accept fallback on slow links |
optional | ~100ms | none | Zero-CLS priority; browser may skip the font on slow connections |
For 90% of sites, swap is the answer. If layout shift is your bigger enemy and the font is decorative, optional trades a guaranteed brand font for a guaranteed-stable layout.
How to detect it
- Lighthouse: run a Performance audit and look for "Ensure text remains visible during webfont load" under Diagnostics. It names every
@font-facemissing afont-displayvalue. - curl -I: confirm the font itself is served efficiently,
curl -I https://yoursite.com/fonts/inter.woff2should returnwoff2with a longcache-control. A slow or uncached font makes FOIT worse, so the two checks are cousins. - DevTools Network panel: filter by Font, throttle to "Slow 3G," and reload. Watch the page, if the text vanishes then pops in, you are seeing FOIT live. The Timing tab shows exactly how long the font blocked render.
How to fix it
- Add
font-display: swapto every@font-facerule you control (or&display=swapon hosted font URLs). - Self-host and
woff2-compress your fonts so they download fast; give them a one-year cache. - Preload the one or two fonts used above the fold so the swap happens before the user notices.
- Add metric overrides (
size-adjust,ascent-override) to match the fallback's footprint and flatten the swap-induced shift. - Re-run Lighthouse and confirm both the font-display diagnostic and any related CLS entries clear.
Fonts are one of the sneakiest performance taxes on a page; the web fonts and performance guide digs into subsetting and self-hosting, and the Core Web Vitals overview ties it back to LCP and CLS scoring.
FAQ
Does font-display: swap hurt my Core Web Vitals?
It helps LCP, because text paints immediately instead of waiting on the font. It can add a little CLS if the fallback and webfont have very different widths, which is exactly what the metric overrides above fix. Net effect on a tuned setup is positive.
What is the difference between FOIT and FOUT?
FOIT is a flash of invisible text, the default blocking behavior, nothing shows. FOUT is a flash of unstyled text, the fallback shows first, then swaps to your font. swap deliberately chooses FOUT because visible fallback text beats a blank screen every time.
Should I use swap or optional for body copy?
Use swap for body copy: readers should always get your intended typeface if it can load. Reserve optional for cases where a stable layout matters more than the exact font, and where the font is small enough that skipping it is no loss.
Do I still need font-display if I preload the font?
Yes. Preloading makes the font arrive sooner, but if it is still in flight when the browser wants to paint, font-display decides whether text shows or hides in that window. Preload and swap work together.
Why is my icon font showing boxes with font-display: swap?
Because swap renders a fallback glyph while the icon font loads, and there is no sensible fallback for a custom icon, so you get tofu boxes. Icon fonts are the one case where block (or better, inline SVG) is correct.
Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.
About SEO ProCheck
Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.
Work With Me
Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.







