Custom web fonts are one of the easiest ways to make a site look polished. They're also a sneaky performance trap: load them carelessly and you get text that flashes invisible, jumps around, or simply takes too long to appear. The good news — you can have beautiful typography and fast text. Here's how.
The two font problems
When the browser needs a custom font it hasn't downloaded yet, it has to decide what to do with the text in the meantime. That decision creates two classic issues:
| Problem | What the user sees |
|---|---|
| FOIT (Flash of Invisible Text) | Blank space where text should be, until the font loads |
| FOUT (Flash of Unstyled Text) | Text shows in a fallback font, then swaps — causing a jump |
FOIT means people stare at nothing; FOUT causes a layout shift (CLS) when the font swaps. Neither is great — but both are fixable.
The fixes
1. Use font-display
The font-display CSS property tells the browser how to behave while a font loads. The usual best choice is swap: show text immediately in a fallback, then swap to the custom font when ready. Users can always read — no invisible text.
font-display value | Behaviour |
|---|---|
swap | Show fallback immediately, swap when loaded (avoids FOIT) |
optional | Use the custom font only if it loads fast; else stick with fallback |
block | Brief invisible period, then custom font (risks FOIT) |
swap (or optional for the strictest performance) keeps text visible.
2. Match your fallback font
The jump from FOUT comes from the fallback and custom fonts being different sizes. Pick a fallback that's close in metrics (and use size-adjust descriptors where supported) so the swap barely moves anything — killing the layout shift.
3. Preload critical fonts
If a font is needed for above-the-fold text, preload it so the browser fetches it early instead of discovering it late. This shrinks the time spent in fallback.
4. Subset and use modern formats
- Subset fonts to the characters you actually use (e.g. Latin only) — often a huge size cut.
- Serve WOFF2, the smallest modern font format.
- Don't load weights you don't use — every extra weight is another download.
5. Self-host (often)
Self-hosting fonts (rather than a third-party stylesheet) removes an extra connection to another origin and gives you full control over caching and font-display.
The one-line rule: use
font-display: swapwith a well-matched fallback, preload the critical font, and ship WOFF2 subsets. That combination gives you instant, readable text that doesn't jump.
Why it matters for Core Web Vitals
Fonts touch two Core Web Vitals: FOIT delays when text is visible (hurting perceived load and sometimes LCP for text-heavy heroes), and FOUT causes CLS. Handling fonts well improves both — and makes the site simply feel faster.
The bottom line
| In one line | |
|---|---|
| The traps | FOIT (invisible text) and FOUT (jumpy swap). |
| Fix FOIT | font-display: swap — always show readable text. |
| Fix FOUT | A size-matched fallback so the swap doesn't jump. |
| Speed | Preload critical fonts, subset, ship WOFF2. |
Web fonts don't have to be a performance tax. Show text immediately with swap, match your fallback, preload what matters, and trim the files — and your typography stays gorgeous and fast.
Related: Core Web Vitals explained, CLS explained, how to speed up your website.