What is font-display?
font-display is a CSS descriptor inside @font-face that controls how a browser handles the "font loading period" — the time between when a page starts rendering and when the custom font file is available to display text.
Without a clear strategy, browsers make different choices. Chrome hides text briefly, Safari hides it longer, Firefox shows fallback text — the same page behaves differently on each browser. font-display unifies the behaviour across browsers by making the choice explicit.
The five values explained
font-display: auto
The browser chooses based on its own heuristics. In practice, Chrome and Firefox behave like swap, while Safari behaves closer to block. This is not recommended because behaviour is inconsistent and can change with browser updates.
font-display: block
Text is invisible for up to 3 seconds while the font loads. If the font arrives within that window, the text appears in the custom font. If not, the browser renders the fallback font — and will swap to the custom font when it finally arrives, no matter how long it takes.
The 3-second block period is the worst part. Users see an empty space where the headline should be. On slower connections or with large font files, LCP (Largest Contentful Paint) can exceed 4 seconds, which is a Critical failure in Core Web Vitals.
Only use block for icon fonts — if fallback glyphs would render as broken symbols, an invisible space is less bad than visible breakage.
font-display: swap
Fallback text renders immediately, and the custom font swaps in when it arrives. There is no invisible-text period. The tradeoff is FOUT (Flash of Unstyled Text) — users briefly see a fallback font, then the custom font. For text content, FOUT is universally preferable to FOIT (Flash of Invisible Text).
swap is the correct default for body text, headlines, and any content users need to read immediately.
font-display: fallback
A middle ground. Text is invisible for a very short block period (roughly 100ms), then falls back to the fallback font. The custom font can only swap in within the first 3 seconds of page load. After that window closes, the fallback font remains for that page load.
The 3-second swap window means: users on slow connections or with slow caches will see the fallback font for that page view. The next page load may show the custom font because the font is cached. This reduces layout shift compared to swap but sacrifices the custom font on slow first loads.
font-display: optional
Text is invisible for ~100ms, then falls back. The custom font only swaps in if it is available within that 100ms window — which is almost never on first load. If the font is already cached from a previous visit, it may be available within 100ms and swap in.
The tradeoff is severe: users on slow first visits essentially never see the custom font. Users on repeat visits do. In exchange, there is zero layout shift caused by font swaps, which is excellent for CLS.
Use optional only when layout stability is more important than typography fidelity — rarely the case for editorial sites, sometimes appropriate for dense dashboards.
Timing comparison
| Value | Invisible period | Fallback visible period | Swap window |
|---|---|---|---|
auto | Varies by browser | Varies | Varies |
block | ~3 seconds | 0 seconds | Unlimited |
swap | 0 seconds | Immediate | Unlimited |
fallback | ~100ms | ~100ms | ~3 seconds from load |
optional | ~100ms | ~100ms | None after initial paint |
font-display strategy except optional allows the font to swap in at any time. That swap causes CLS (Cumulative Layout Shift) if the fallback font has different metrics than the custom font. See the metric-override section below to eliminate this shift.Impact on Core Web Vitals
Largest Contentful Paint (LCP)
LCP measures when the largest visible element renders. If your LCP element is a headline in a custom font:
blockdelays LCP until the font arrives — typically 1–4 seconds on first load. Critical failure.swapreports LCP as soon as the fallback text paints — often under 1 second. Pass.fallbackdelays LCP by ~100ms only. Pass.optionalreports LCP as soon as the fallback text paints. Pass.
Cumulative Layout Shift (CLS)
CLS measures unexpected layout movement. If your custom font has different metrics (line heights, character widths) than the fallback font, the text reflows when the font swaps in. This is a layout shift.
swapcan cause CLS if the swap happens after first paint (common).fallbackreduces CLS because most swaps happen within the 100ms window before users perceive them.optionaleliminates CLS entirely by not swapping after first paint.blockhas minimal CLS from fonts but maximum LCP harm.
The best of both worlds is swap combined with metric-adjusted fallbacks (below). This gives instant text paint (good LCP) with negligible layout shift (good CLS).
Metric-adjusted fallbacks
Modern CSS provides four descriptors that adjust a fallback font's metrics to match your primary font. When the font swaps, the text barely shifts because the fallback was already rendering at approximately the same size and position.
@font-face {
font-family: "Inter Fallback";
src: local("Arial");
size-adjust: 107%;
ascent-override: 90%;
descent-override: 22.43%;
line-gap-override: 0%;
}
body {
font-family: "Inter", "Inter Fallback", sans-serif;
}
The exact values depend on the metrics of both fonts. Chrome DevTools calculates these values automatically in the Network panel: select your font, look at the "Fallback" tab, and copy the suggested CSS. Firefox and Safari show similar data.
This technique reduces CLS from ~0.05 to under 0.01 in most cases — enough to pass Core Web Vitals without sacrificing custom fonts.
Recommendations by content type
| Content type | font-display | Rationale |
|---|---|---|
| Body text | swap | Reading must never be blocked; readability of fallback text is acceptable |
| Headlines (LCP element) | swap | Fallback renders instantly; metric-override prevents shift |
| Hero section headline | swap + metric override | Highest-impact LCP element; swap + adjusted fallback is optimal |
| UI labels and buttons | swap | Users need to read controls immediately |
| Icon fonts | block | Fallback glyphs render as broken symbols; blocking is less bad |
| Decorative display fonts | optional | Custom font is nice-to-have; fallback is fine |
| Print-style documents | fallback | Balance reading speed with visual fidelity |
Common mistakes
- Using
blockfor body text — guarantees LCP failure on slow connections. - Using
autoand assuming it behaves likeswap— behaviour varies by browser. - Forgetting
font-displayentirely — defaults toauto, which is unpredictable. - Mixing strategies across fonts — a body font with
swapand a heading font withblockcreates inconsistent LCP behaviour. - Not including metric overrides — even
swapcan cause CLS if the fallback metrics are very different.
Generate your @font-face CSS
Use the OmniFonts font-display Generator to build a complete @font-face rule with your chosen strategy, or the @font-face Generator for a full rule with all properties including metric overrides.
Frequently asked questions
What is the best font-display value?
swap for body text and headings. optional when you cannot accept any layout shift. block only for icon fonts.
Does font-display affect Core Web Vitals?
Yes. swap minimizes LCP delay. block can severely harm LCP. optional has the smallest CLS impact but sacrifices custom font display on slow connections.
What is FOIT and FOUT?
FOIT (Flash of Invisible Text) is caused by block. FOUT (Flash of Unstyled Text) is caused by swap. FOUT is universally preferred over FOIT.
Is font-display: auto ever a good choice?
Rarely. auto delegates to browser heuristics which differ across browsers. Explicitly choosing swap is more reliable.
Can I use metric overrides with Google Fonts?
Yes, by adding a @font-face rule that declares the fallback with metric overrides, then including it in your font-family stack after the Google Font. Chrome DevTools calculates the exact values you need.