Skip to main content

· Performance · 6 min read

font-display Explained: swap, optional, fallback, or block?

What each font-display value does while a web font loads, and how to pick one for body text, headings, and icons without hiding text or jolting the layout.

A web font is never there instantly. Until the file arrives, the browser has two choices: hide the text, or show it in a fallback font and switch when the web font is ready. The font-display descriptor lets you make that choice for each font.

This guide explains what happens behind each value and which one to use where.

The font display timeline

The CSS Fonts specification splits a font’s loading time into three periods. The clock starts when the browser first tries to use the font, not when the page starts loading.

  1. Block period. Text that uses the font is drawn with an invisible fallback. If the font arrives now, it is used straight away. Visitors see empty space where the text will be.
  2. Swap period. Text is drawn in a visible fallback font. If the web font arrives now, the browser swaps it in.
  3. Failure period. The browser gives up on the font for this page, and the fallback stays.

Every font-display value is a different length for the first two periods. MDN’s font-display reference describes them in the same terms.

The five values

ValueBlock periodSwap periodWhat visitors see
autoBrowser decidesBrowser decidesUsually like block
blockShort (spec suggests 3 s)InfiniteInvisible text for up to a few seconds, then the font
swapTiny (100 ms or less)InfiniteFallback text at once, replaced whenever the font arrives
fallbackTiny (100 ms or less)Short (spec suggests 3 s)Fallback at once; swaps only if the font arrives soon
optionalTinyNoneThe web font only if it is ready almost immediately

The durations in brackets are the ones the specification recommends; browsers may use different numbers.

auto

The browser chooses. web.dev’s Best practices for fonts notes that Chromium-based browsers and Firefox hide text for up to 3 seconds by default. If you do not set font-display, assume visitors on slow connections may see blank text.

block

Text stays invisible for a short time, then shows in a fallback, then switches to the web font whenever it arrives. Use it only when the fallback would be actively wrong, not just less pretty. Lighthouse flags fonts that can hide text with its Ensure text remains visible during webfont load audit.

swap

Text appears immediately in a fallback font, and the web font replaces it whenever it loads, even many seconds later. Visitors can always read, but the late switch can move text around if the two fonts have different sizes. It is a common choice; Google Fonts, for example, applies it when the stylesheet URL includes display=swap.

fallback

A middle ground. Text appears almost immediately in the fallback. If the web font arrives within the short swap period, it is used. If it arrives later, the page keeps the fallback, so there is no late jump.

optional

The browser uses the web font only if it is available almost immediately, for example from the cache or because it was preloaded. Otherwise the page keeps the fallback for its whole lifetime: no swap and no shift. Depending on the browser, the file may still finish downloading, so it is ready from the cache on the next page.

Since Chrome 83, preloading an optional font makes Chrome wait briefly (about 100 ms) for it before the first render, which greatly improves the chance that the font is used on the first visit. web.dev explains this in Prevent layout shifting and flashes of invisible text by preloading optional fonts.

How to choose

Ask two questions: how bad is it if visitors briefly see a different font, and how bad is it if text moves when the font changes?

Body text: swap or optional. Long paragraphs need to be readable at once.

  • Use swap if the brand font matters on every visit. Then reduce the jump when it swaps by giving the fallback similar metrics; see How to reduce layout shift from web fonts, or calculate the values for your font with the font fallback generator.
  • Use optional if stability and speed matter most. web.dev recommends it when performance is the priority. Pair it with a preload of the main text font so most visitors still get it.

Headings and brand text: swap, sometimes block. A short heading in a fallback font for a moment is usually fine. block can make sense for a logo-like wordmark set in text, where a fallback would look broken. Keep those fonts small so the wait is short.

Fonts used further down the page: fallback or swap. By the time a visitor scrolls there, the font has usually arrived.

Icon fonts: block, or better, no icon font. An icon font’s fallback shows random letters or ligature names such as “search” in place of the icon. block hides that. web.dev’s advice is to replace icon fonts with SVG icons altogether.

You can mix values on one page, because font-display is set per @font-face rule:

/* Body text: keep the layout steady */
@font-face {
  font-family: 'Brand Text';
  src: url('/fonts/brand-text-regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: optional;
}

/* Headings: always show the brand font once it arrives */
@font-face {
  font-family: 'Brand Display';
  src: url('/fonts/brand-display-bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

body {
  font-family: 'Brand Text', system-ui, sans-serif;
}

h1,
h2 {
  font-family: 'Brand Display', 'Brand Text', system-ui, sans-serif;
}

Common mistakes

Putting font-display on an element. It is an @font-face descriptor, not a CSS property. This does nothing:

/* Wrong: font-display is ignored here */
body {
  font-family: 'Brand Text', sans-serif;
  font-display: swap;
}

Forgetting third-party stylesheets. If a font service writes the @font-face rules for you, you cannot edit them, so use the service’s own option, such as the display parameter on Google Fonts.

Using swap with a very different fallback. If the fallback is much wider or taller than the web font, swap trades invisible text for a visible jump. Pick a closer fallback, or adjust its metrics with the font fallback generator.

Choosing optional and never preloading. On a first visit over a slow connection the web font may never show. That is by design, but make sure it is what you want for that font.

Test it

  1. Open your browser’s developer tools, disable the cache, and pick a slow network preset in the Network panel.
  2. Reload and watch the first few seconds. Is the text invisible, in a fallback, or in the web font?
  3. Turn on layout shift highlighting (in Chrome, the Rendering panel has a “Layout Shift Regions” option) to see whether the swap moves anything.
  4. Reload again with the cache enabled to see what repeat visitors get.

Where FontPivot fits

The web font kit from the font converter and the font viewer writes font-display: swap into its @font-face rule by default, because it keeps text visible in every case. To use optional, fallback, or another value, change the font-display setting in the converter’s advanced options; the viewer’s kit follows the same setting. If you are converting a desktop font for the first time, start with TTF to WOFF2 or OTF to WOFF2.

Further reading

Share:
Back to guides

Related guides

All guides »