font-display is a descriptor inside a @font-face rule that controls what the browser paints between asking for a font file and receiving it. It takes five values: auto, block, swap, fallback and optional. They differ on two questions: how long the text stays invisible while the browser waits, and whether the browser is still willing to switch to the web font once it finally arrives. The descriptor does not make a font download faster. It decides what the visitor sees during the download.

The default is a blocking period, not “show the fallback”

Left unset, browsers hide the text rather than draw it in a fallback typeface. web.dev states the length: “By default, Chromium-based and Firefox browsers block text rendering for up to 3 seconds if the associated web font has not loaded.”

Lighthouse has an audit for exactly this, and its description names the symptom: “Fonts are often large files with slow load times. Some browsers hide text until the font loads, causing a flash of invisible text (FOIT).”

The cost lands on FCP, because a page with no visible text has not painted content. web.dev puts that connection directly: “If a web font has not loaded, browsers typically delay text rendering. In many situations, this delays First Contentful Paint (FCP).”

The five values

ValueText while waitingFont swapped in when it arrives
autobrowser default, in practice a block periodyes
blockinvisible for a short block periodyes
swapfallback typeface immediatelyyes
fallbackfallback after a very short blockonly within a short window
optionalfallback after a very short blockno, the font is left for the next visit

Two of them cover almost every real decision. swap says the words matter more than the typography, which is the right answer for body text. optional says the typography is decoration, and it is the only value that protects the layout completely, because the browser either has the font in time or never applies it on that view.

What we can see, and on which platforms

Our proxy reads a page’s markup and adds a display setting where the declaration is in the HTML: a Google Fonts stylesheet link with no display= parameter, or an @font-face inside an inline <style>. Share of audited sites carrying such a declaration with no display setting, snapshot of 2026-08-04:

PlatformSitesFont declared in the HTML with no display setting
Duda5145
WooCommerce5718
Elementor306
WordPress6410
Bitrix282
Webflow340
Wix320
Squarespace380

The three zeros are a limit of the measurement and not a clean bill of health. Those platforms declare their fonts in external stylesheets, which this pass does not rewrite, so we see no declaration rather than a correct one. Read the table as “of the declarations visible in the HTML”, which is also all a browser extension or a quick view-source will tell you. Tilda is absent for a different reason: it runs a different filter set, where fonts are inlined instead.

The context those figures sit in is in our study of web fonts across 452 audited sites: 436 of them load at least one font file, five files at the median.

What swap costs

swap removes invisible text by introducing a visible change of typeface, and if the fallback has different metrics from the web font, the text reflows when the swap happens. Line lengths change, everything below moves, and that is CLS. The fix is not to go back to blocking. It is to make the fallback match: size-adjust, ascent-override and descent-override on a local fallback @font-face bring the substitute close enough that the swap stops moving the page.

This trade is real enough that our own filter declares it. font-display: swap is recorded in our pipeline as improving FCP and as a possible cost to CLS, and both halves show up in measurement.

In code

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

For a Google Fonts stylesheet the same setting is a URL parameter:

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

What WebSpeed does with it

Two narrow edits, both in the HTML. A Google Fonts stylesheet link with no display= gets &display=swap appended, and an @font-face block in an inline <style> gets font-display: swap added. Fonts declared in an external stylesheet are outside this pass, which is why the table above is a floor: on the platforms that keep their @font-face rules in a separate file, the setting is the site’s own to make.