Text is invisible for a second while a web font loads, then it pops in. What's happening and how do you control it?
Understanding the invisible-text problem, the font-display swap period, and preloading.
When text uses a web font that hasn't downloaded yet, the browser must decide what to show meanwhile, and the default is bad for perceived performance. FOIT — Flash Of Invisible Text — is when the browser hides the text entirely while waiting for the font (historically up to 3s), so the user stares at blank space; if the font is your LCP text, this delays LCP directly. FOUT — Flash Of Unstyled Text — is when the browser shows a fallback system font immediately, then swaps to the web font when it arrives, causing a visible reflow/restyle. The `font-display` descriptor in @font-face lets you choose the tradeoff: `swap` shows the fallback immediately and swaps in the web font whenever it loads (favor content visibility, accept the swap — good default for body text); `optional` gives a tiny block period and, if the font isn't cached/fast, just keeps the fallback for this visit (best for CLS/LCP, the font may not appear at all first load); `fallback` is a compromise; `block` is the FOIT behavior. Beyond font-display: (1) `<link rel=preload as=font crossorigin>` the critical font so it starts downloading early instead of being discovered late (fonts are referenced from CSS, so they're found only after CSSOM). (2) Self-host and subset the font to the glyphs you use to cut bytes. (3) Use WOFF2. (4) Reduce the swap's layout shift by choosing a fallback with similar metrics (size-adjust / ascent-override, or the 'f-mods'). The combination — preload + font-display: swap (or optional) + WOFF2 subset — gives fast visible text with minimal shift.
Fixing invisible or shifting text during load; tuning web-font delivery.
<!-- Discover the critical font early instead of after CSS parses -->
<link rel="preload" href="/fonts/inter.woff2" as="font"
type="font/woff2" crossorigin>
<style>
@font-face {
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
font-display: swap; /* show fallback now, swap when ready (no FOIT) */
/* Reduce the swap's layout shift by matching fallback metrics: */
size-adjust: 105%;
ascent-override: 90%;
}
body { font-family: 'Inter', system-ui, sans-serif; }
</style>