How Does CSS font-display Optimize Font Loading?

The CSS font-display descriptor optimizes web font loading by controlling how browsers render text while a custom web font file is being fetched. By managing the visual timeline—specifically the balance between invisible fallback periods and fallback font rendering—font-display helps web developers minimize user-facing issues like Flash of Invisible Text (FOIT) and Flash of Unstyled Text (FOUT), improving perceived performance and Core Web Vitals metrics.

The Font Loading Timeline

When a browser encounters an @font-face rule, it divides the loading lifecycle of that font into three distinct periods:

  1. Font Block Period: The browser temporarily hides text rendered with the custom font, rendering an invisible fallback while waiting for the download.
  2. Font Swap Period: If the custom font has not loaded, the browser renders the text using a fallback system font. When the custom font finishes loading, the browser swaps it in.
  3. Font Failure Period: If the custom font fails to download or exceeds the swap deadline, the browser permanently uses the fallback system font for the current page session.

The font-display descriptor allows developers to adjust the duration of these three periods.

Supported font-display Values

Developers can set five different values on the font-display descriptor inside @font-face:

font-display: auto

The browser uses its default font-loading behavior. Most modern desktop and mobile browsers apply a short block period (around 3 seconds) followed by an infinite swap period. This often leads to noticeable FOIT on slower mobile connections.

font-display: swap

The font block period is extremely short (virtually 0ms), followed by an infinite swap period. The browser immediately renders the text using a fallback system font and swaps to the custom font as soon as it arrives. This eliminates FOIT entirely, ensuring text is immediately readable, though it can cause a visual shift (FOUT) when the new font renders.

font-display: fallback

This option enforces an extremely brief block period (around 100ms) and a short swap period (around 3 seconds). If the font loads quickly, it renders without text shift. If it takes longer, the fallback appears, and if it fails to arrive within roughly 3 seconds, the fallback font is locked for the remainder of the session to avoid disruptive mid-read layout shifts.

font-display: optional

The font block period is tiny (around 100ms), and there is zero swap period. The browser decides whether to use the custom font depending on the connection speed. If the font is already cached or arrives within the initial ~100ms window, it is rendered; otherwise, the fallback font is used permanently for that page view. The custom font is downloaded in the background so it is available for subsequent page visits.

font-display: block

The browser applies a short block period (around 3 seconds) followed by an infinite swap period. This mimics traditional browser behavior and is best reserved for icon fonts or critical branding elements where rendering fallback text could break the layout or interface meaning.

Impact on Core Web Vitals and User Experience

Using font-display directly affects two major Core Web Vitals metrics:

Practical Implementation

To implement font-display, include the descriptor directly within the @font-face declaration in your stylesheet:

@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/opensans-regular.woff2') format('woff2');
}

By choosing the appropriate font-display strategy based on the priority of the text—such as swap for body copy, optional for non-essential stylings, and block for icon sets—developers can balance visual polish with optimal loading speeds.