Insights

Web Font Loading — How to Stop Invisible Text and Layout Shift

Custom fonts can hide text while they load and shift the layout when they arrive. Learn what FOIT and FOUT are, how font-display works, how to match fallback font metrics, and when a system font is the better choice.

Purushottam Kumar Suman
Purushottam Kumar SumanSeptember 28, 20265 min read
Founder & CEO, DeepSync
Typography and layout being reviewed on a screen

Short answer: a web font is a file the browser must download before it can draw text in that typeface. Until it arrives, the browser either hides the text or shows a fallback font and swaps later, which can move the layout. Use font-display: swap or optional, preload the one or two fonts used above the fold, self-host them in WOFF2, limit the number of weights, and adjust the fallback font's metrics so the swap causes no shift.

Table of Contents

  1. Two Problems
  2. font-display
  3. Loading Fonts Sooner
  4. Removing the Shift
  5. When to Use System Fonts
  6. Key Takeaways

Two Problems

Invisible text (FOIT). The browser leaves the text blank while the font downloads. On a slow connection the visitor sees images and boxes with no words. If the headline is the largest element, this delays LCP (LCP).

Unstyled text then swap (FOUT). The browser shows a fallback font, then replaces it. If the two fonts have different widths and heights, lines re-wrap and everything below moves. This contributes to CLS (CLS).

Showing text in a fallback is the better of the two, as long as the swap does not move the page.

font-display

The font-display descriptor in @font-face controls the behavior.

ValueBehaviorUse
blockHide text briefly, then swap whenever the font arrivesIcon fonts only
swapShow fallback at once, swap whenever the font arrivesBody and headings, with matched fallback metrics
fallbackVery short hide, swap only if the font arrives quicklyA compromise
optionalVery short hide, use the font only if it is already availableBest for stability; the first visit may use the fallback
@font-face {
  font-family: "Brand Sans";
  src: url("/fonts/brand-sans-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

optional gives no layout shift at all, at the cost that a first-time visitor on a slow network sees the fallback for that page view. For many sites this is a good trade.

Loading Fonts Sooner

  1. Self-host. Serving fonts from your own domain avoids a connection to another host. Third-party font services no longer share a cache across sites, so the old argument for them has gone.
  2. Use WOFF2. It is the smallest widely supported format. Other formats are no longer needed for current browsers.
  3. Preload the critical font.
<link rel="preload" href="/fonts/brand-sans-400.woff2" as="font" type="font/woff2" crossorigin>

The crossorigin attribute is required for font preloads, even on the same domain. Preload only the one or two files used above the fold. Preloading many fonts delays more important resources.

  1. Limit weights and styles. Each is a separate file. Regular and bold cover most designs. A variable font can replace several files with one.
  2. Subset. If the site uses only Latin characters, do not ship the full character set. For sites in Indian languages, subset to the script in use, since full Devanagari or Tamil fonts are large. Use unicode-range so the browser downloads a script's file only when the page contains it.
  3. Cache for a long time with versioned file names.

Removing the Shift

The shift at swap comes from the fallback and the web font having different metrics. You can adjust the fallback to match.

@font-face {
  font-family: "Brand Sans Fallback";
  src: local("Arial");
  size-adjust: 104%;
  ascent-override: 92%;
  descent-override: 24%;
  line-gap-override: 0%;
}

body {
  font-family: "Brand Sans", "Brand Sans Fallback", sans-serif;
}

These descriptors scale the local fallback so that text occupies nearly the same space as the web font. The values depend on your font. Several frameworks generate them automatically, and there are tools that calculate them from a font file.

Also:

  • Set a fixed line height in CSS so that line spacing does not depend on the font.
  • Avoid icon fonts. If they fail or load late, visitors see blank squares or odd letters. Use SVG icons.
  • Do not load fonts from CSS that is itself loaded late. The browser discovers the font only after the stylesheet.

When to Use System Fonts

A system font stack uses the typeface already on the device.

body {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

No download, no hidden text, no shift. For application interfaces, dashboards, checkout pages, and content-heavy sites on slow networks, this is often the right choice. Branding can be carried by a single custom font for headings.

The question to ask is whether the custom font earns its cost. On a checkout page it almost never does.

Seeing It in Real Sessions

Font problems are hard to notice on a fast connection, because the font is cached after the first visit. Visitors on slow mobile networks, and first-time visitors, experience them.

In session recordings, look at the first seconds of mobile sessions on entry pages:

  • Blocks with no text, then text appearing.
  • A headline changing width and the content below jumping.
  • A tap landing on the wrong link just after the swap.

Pair that with field data: CLS and LCP by page and device (performance). A page whose LCP element is a headline and whose LCP is poor is a candidate for a font problem.

To test, clear the cache, throttle the network in developer tools, and reload.

Test as a first-time visitor

You have had your fonts cached for months. Open the site in a private window on a throttled connection to see what a new visitor from an ad sees.

Key Takeaways

  • Fonts can hide text and shift layout.
  • Use font-display swap or optional; self-host WOFF2; preload sparingly.
  • Match fallback metrics to remove the shift.
  • System fonts avoid the problem entirely.

Conclusion

Typography is part of a brand. So is a page that does not jump. With a matched fallback you can have both.

Start free with DeepSync.

Frequently Asked Questions

Was this article helpful?

Ready to understand
users like never before?

Join thousands of teams who use DeepSync to uncover insights,improve experiences, and build better products—faster.

Quick & easy onboarding
See results in real time
Enterprise-grade security