
What is the font-display property and which value should you use?
- Sajjad
- Typography
- 11 Oct, 2026
font-display is a descriptor you add inside an @font-face rule to tell the browser what to do with text while that font is still downloading. It has five values: auto, block, swap, fallback and optional. Each one sets how long text stays invisible (the block period) and how long the browser is still willing to switch from a fallback to the web font (the swap period). For most body and heading text, swap is the safe default because text is always visible, while optional is the best choice when avoiding layout shift matters more than showing the custom font on a first visit. Use block only for icon fonts, and fallback as a compromise between the two.
A single line of CSS here decides whether visitors on a slow connection see a blank page, a page that jumps as fonts swap, or a stable page in a fallback font. It also affects Largest Contentful Paint and Cumulative Layout Shift. In this article you'll learn how the font loading timeline works, exactly what each value does, how to set it for self-hosted fonts, Google Fonts and frameworks, and how to choose the right value for each font on your site.
The Font Display Timeline
When the browser first needs a web font that isn't ready, it starts a timer and moves through three periods:
- Block period: Text using the font is rendered invisibly. If the font loads during this period, it's used straight away.
- Swap period: Text is rendered in a fallback font. If the web font loads during this period, the browser swaps it in.
- Failure period: The browser stops waiting. The fallback stays for the rest of the page's life, even if the font finishes downloading later.
Every font-display value is simply a different combination of block and swap period lengths. The CSS Fonts specification gives recommended timings, and browsers follow them closely.
The Five Values
| Value | Block period | Swap period | In plain terms |
|---|---|---|---|
auto | Browser decides | Browser decides | Usually behaves like block |
block | Short, about 3 s | Infinite | Hide text, then always swap |
swap | Extremely short, 100 ms or less | Infinite | Show fallback, always swap |
fallback | Extremely short, 100 ms or less | Short, about 3 s | Show fallback, swap only if fast |
optional | Extremely short, 100 ms or less | None | Use the font only if it's almost instant |
auto
The default when you don't set anything. The browser chooses its own strategy, which in current browsers is a block period of up to about three seconds. Lighthouse flags this because it can leave text invisible on slow connections.
block
Text is hidden for up to about three seconds, then a fallback appears, and the web font replaces it whenever it arrives, however late. This is the classic flash of invisible text followed by a possible late swap.
Use block when showing the wrong font would be worse than showing nothing. Icon fonts are the main example, because their code points render as meaningless characters in a fallback font.
swap
The block period is almost zero, so the fallback appears immediately. The web font is swapped in whenever it loads, with no time limit.
This guarantees text is always visible and that visitors eventually see your font. The trade-off is that a late swap can cause a visible restyle and layout shift, possibly after the visitor has started reading.
fallback
Like swap, the fallback appears almost immediately. But the browser only waits about three seconds for the web font. If it arrives in time it's swapped in; if not, the fallback stays for that page view. The font still finishes downloading and is cached for the next page.
This avoids the worst case of swap, a jarring change long after the page has settled, while still showing the custom font to most visitors.
optional
The browser gives the font a tiny window, and if it isn't ready, the fallback is used for the whole page view with no swap at all. Browsers may also decide not to download the font at all on very slow connections, or to give it lower priority. When it does download, it's cached, so the next page usually renders with the web font immediately.
This value eliminates font-swap layout shift. It's ideal when the web font is a refinement rather than essential to the brand.
How to Set font-display
Self-Hosted Fonts
Add the descriptor to every @font-face rule. It applies per face, so you can use different values for different files:
@font-face {
font-family: "Atkinson Hyperlegible";
src: url("/fonts/atkinson-hyperlegible-400.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Atkinson Hyperlegible";
src: url("/fonts/atkinson-hyperlegible-700.woff2") format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
font-display only works inside @font-face. Writing it on an element selector does nothing:
/* This has no effect */
body {
font-display: swap;
}
Google Fonts
Add the display parameter to the stylesheet URL. Google then writes the value into every @font-face rule it returns:
<link
href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&display=swap"
rel="stylesheet"
>
You can use any of the five values, for example &display=optional.
Fontsource Packages
Fontsource's CSS files set font-display: swap by default. If you want a different value, write your own @font-face rules pointing at the package's font files instead of importing the provided CSS.
Next.js
The next/font module accepts a display option and defaults to swap:
import { Atkinson_Hyperlegible } from "next/font/google";
const atkinson = Atkinson_Hyperlegible({
weight: ["400", "700"],
subsets: ["latin"],
display: "optional",
});
WordPress theme.json
Block themes that register fonts in theme.json can set fontDisplay for each face:
{
"version": 3,
"settings": {
"typography": {
"fontFamilies": [
{
"name": "Atkinson Hyperlegible",
"slug": "atkinson",
"fontFamily": "\"Atkinson Hyperlegible\", sans-serif",
"fontFace": [
{
"fontFamily": "Atkinson Hyperlegible",
"fontWeight": "400",
"fontStyle": "normal",
"fontDisplay": "swap",
"src": ["file:./assets/fonts/atkinson-hyperlegible-400.woff2"]
}
]
}
]
}
}
}
Which Value Should You Use?
The right value depends on the role of each font.
Body Text
Readers need body text immediately. Use swap if your brand relies on the font, or optional if layout stability matters more. With a well-matched fallback, optional is often the best overall experience: first-time visitors on slow connections read in a familiar system font, and everyone else gets the web font with no shift.
Headings and Display Type
Headlines are often the Largest Contentful Paint element, and their typeface carries much of the visual identity. swap keeps them visible and makes sure the custom font always appears. Pair it with a preload so the swap happens early, ideally before the visitor notices.
Logos and Wordmarks Set in Text
If a logo is set in live text with a web font, a fallback can look wrong. Consider using an SVG for the logo instead. If you must use text, block combined with a preload keeps the brand consistent at the cost of a short invisible period.
Icon Fonts
Use block. A fallback font would render icon glyphs as stray letters or boxes. Better still, replace icon fonts with inline SVG, which avoids the problem entirely.
Secondary and Decorative Fonts
Fonts used for small accents, such as a script used for a single tagline, rarely justify any layout shift. optional or fallback keeps them from disrupting the page.
A Quick Decision Guide
- Text must be visible and the font must eventually appear:
swap. - Text must be visible and the page must never shift:
optional. - You want the font for most visitors but no late surprises:
fallback. - Wrong glyphs would be worse than none:
block. - Never rely on:
auto.
How font-display Interacts With Preloading
Preloading starts the font download much earlier, which changes how each value behaves in practice:
- With swap and fallback: A preloaded font often arrives during or just after the first paint, so the fallback is only visible for a moment.
- With optional: Preloading makes it far more likely the font is ready within the tiny window, so most first-time visitors get the web font with no swap. Chrome also gives preloaded optional fonts a brief chance to load before the first render, specifically to reduce layout shift.
<link
rel="preload"
href="/fonts/atkinson-hyperlegible-400.woff2"
as="font"
type="font/woff2"
crossorigin
>
That combination, optional plus a preload of the main body font, is one of the most effective font loading setups available. See the guide on how to preload fonts correctly for the details.
How font-display Interacts With Layout Shift
font-display decides when a swap can happen; it doesn't change how much a swap moves the page. With swap and fallback, the size of the layout shift depends on how closely the fallback matches the web font. That's where fallback metric overrides come in:
@font-face {
font-family: "Atkinson Fallback";
src: local("Arial");
size-adjust: 102%;
}
body {
font-family: "Atkinson Hyperlegible", "Atkinson Fallback", Arial, sans-serif;
}
The percentage is a placeholder; calculate it from the real metrics of the two fonts. A well-tuned fallback combined with swap gives you the custom font for everyone with very little visible movement.
Testing Your Choice
- In DevTools, disable the cache and throttle the network to Slow 4G.
- Reload and watch how text appears. Note whether there's a blank period and whether text moves when the font arrives.
- Repeat with each candidate value.
- Record a Performance trace and check the Layout shifts track around the time fonts finish loading.
- Run Lighthouse and confirm the "Ensure text remains visible during webfont load" audit passes.
Try a cached repeat visit as well. With optional, a first visit may show the fallback, but the second should show the web font immediately.
FAQ: The font-display Property
For most text, swap or optional. Use swap when visitors must always see your font, and optional when avoiding layout shift is the priority. Reserve block for icon fonts and avoid relying on auto.
No. font-display is a descriptor that only works inside an @font-face rule. Putting it on body or another selector has no effect.
No. The browser still downloads and caches it in most cases. It just won't swap it in on the current page if it misses the brief initial window. The next page usually uses it straight away.
Usually because some @font-face rules don't include it, often in third-party CSS or a plugin stylesheet. With Google Fonts, check that the URL includes the display parameter.
Yes. All current versions of Chrome, Edge, Firefox, Safari and Opera support it. Older browsers that don't simply ignore the descriptor and use their default behaviour.
Not necessarily. It's set per @font-face rule, so you can use swap for headings, optional for body text and block for an icon font if that suits each role.
Conclusion
The font-display descriptor controls a short but important moment: the time between a page rendering and its web fonts arriving. By setting the length of the block and swap periods, its five values let you choose between invisible text, a guaranteed swap, a time-limited swap or no swap at all.
For almost every site, swap and optional are the values that matter. Use swap when your font is essential, optional when stability comes first, block only for icon fonts, and never leave it to auto. Combine your choice with a preload for the main font and a metric-matched fallback, and font loading becomes something your visitors barely notice.


