font-display: swap Explained

How to eliminate invisible text during web font loading and improve Core Web Vitals

Updated January 2025 8 min read

Quick Answer

font-display: swap tells the browser to show text immediately using a fallback font, then swap to your custom font once it loads. Add it to your @font-face rule:

@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2') format('woff2');
  font-display: swap;
}

What is font-display?

The font-display CSS property controls how a web font is displayed while it's loading. It's part of the @font-face rule.

When a browser encounters text styled with a web font that hasn't loaded yet, it must decide: should it show nothing (invisible text), show a fallback font, or wait? The font-display property gives you control over this behavior.

Without font-display, browsers default to making text invisible for up to 3 seconds while fonts load. This "Flash of Invisible Text" (FOIT) hurts user experience and Core Web Vitals scores.

All font-display values explained

auto

Browser decides. Usually behaves like block. Not recommended.

block

Short invisible period (~3s), then shows fallback indefinitely until font loads. Causes FOIT.

swap ← Recommended

Zero invisible period. Shows fallback immediately, swaps when font loads. Best for important text.

fallback

Very short invisible period (~100ms), then fallback. Only swaps if font loads quickly (~3s). Good balance.

optional

Very short invisible period (~100ms). Browser decides if it should use the font at all. Best for slow connections.

Why use font-display: swap?

Eliminates invisible text

Text is always visible, even on slow connections

Improves Largest Contentful Paint (LCP)

Critical text renders immediately, improving Core Web Vitals

Passes Lighthouse audits

Fixes "Ensure text remains visible during webfont load"

Better user experience

Users can read content immediately instead of waiting

How to implement font-display: swap

Self-hosted fonts

Add font-display: swap to your @font-face declarations:

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/inter-regular.woff2') format('woff2'),
       url('/fonts/inter-regular.woff') format('woff');
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/inter-bold.woff2') format('woff2'),
       url('/fonts/inter-bold.woff') format('woff');
}

Variable fonts

Same approach works for variable fonts:

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900; /* Full weight range */
  font-display: swap;
  src: url('/fonts/Inter-Variable.woff2') format('woff2-variations');
}

Using font-display with Google Fonts

Google Fonts supports font-display via the &display= parameter:

<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">

Pro tip: Self-host for best performance

While Google Fonts is convenient, self-hosting fonts gives you more control and eliminates third-party requests. Use Sift to download optimized, subsetted versions of any variable font.

swap vs optional: which should you use?

ScenarioRecommendation
Brand/heading fontsswap
Body text (long articles)optional or fallback
Users on slow connectionsoptional
Layout shift is a concernoptional
Design consistency is criticalswap

The tradeoff: swap guarantees your font appears but may cause a layout shift when it loads. optional prevents layout shift but may show the fallback font permanently on slow connections.

Fixing Lighthouse font warnings

If Lighthouse shows "Ensure text remains visible during webfont load", adding font-display: swap fixes it.

Complete fix checklist:

  1. Add font-display: swap to all @font-face rules
  2. If using Google Fonts, add &display=swap parameter
  3. Preload critical fonts with <link rel="preload">
  4. Subset fonts to reduce file size and load time

Preloading fonts

Combine font-display with preloading for best results:

<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>

Best practices

1. Use WOFF2 format

WOFF2 offers 30% better compression than WOFF. Faster downloads mean faster swaps.

2. Subset your fonts

Remove unused characters to dramatically reduce file size. A full Inter font is 387KB; subsetted for Latin can be under 20KB.

3. Choose similar fallback fonts

Pick a system font with similar metrics to minimize layout shift when swapping.

4. Use font-display per use case

It's okay to use swap for headings and optional for body text in the same project.

Optimize your fonts with Sift

Sift generates optimized, subsetted WOFF2 fonts with font-display: swap CSS snippets ready to copy. Reduce font file sizes by 70% or more.

Try Sift free →

Frequently Asked Questions

What does font-display: swap do?
font-display: swap tells the browser to immediately show text using a fallback font while the custom web font loads in the background. Once loaded, the browser swaps to the custom font. This eliminates the "flash of invisible text" (FOIT) that occurs when fonts load slowly.
Does font-display: swap affect Core Web Vitals?
Yes. Using font-display: swap improves Largest Contentful Paint (LCP) by ensuring text is visible immediately. It also helps pass the Lighthouse "Ensure text remains visible during webfont load" audit.
What are all the font-display values?
The font-display property accepts five values: auto (browser default), block (brief invisible period), swap (immediate fallback, then swap), fallback (short invisible period, may not swap if slow), and optional (very short invisible period, browser chooses whether to use font).
Should I use font-display: swap or optional?
Use swap for brand fonts where design consistency matters. Use optional for body text where preventing layout shift is more important than using the exact font. optional is better for users on slow connections.
Does font-display work in all browsers?
Yes! font-display has excellent browser support. It works in Chrome 60+, Firefox 58+, Safari 11.1+, Edge 79+, and all modern mobile browsers. Browsers that don't support it simply ignore it.

Related Guides

Last updated: January 2025

Found this helpful? Try Sift to optimize your fonts.