This is a small explainer that Monica Dinculescu built for a talk on web fonts and performance.
Before we talk about what font-display
is, let's talk about the lifetime of a web font. For a super
detailed explanation of where web fonts fit in the browser rendering process, Ilya Grigorik has an
amazing blog post
on web font optimization. But, if we're just trying to understand the basics, there are basically three
parts to it:
During the block period, the browser renders your text in an invisible font. This is why on a lot of webfont-heavy websites, during the first load of the page you will see no text or worse, phantom underlines.
During the swap period, the browser renders your text in the fallback font (in the example in the diagram, that would be the default `serif` font.
The failure period means no font has been found, in which case the browser renders your text in the fallback font, as above.
With the new font-display
attribute, you can control the length of each of these periods, and what happens when one of them fails.
There are 4 different values:
block
, swap
, fallback
and optional
. There's also auto
,
which usually ends up being the same as block
. These values
are supported on all modern browsers (IE not included), but double
check the compatibility
table for the latest!
The font display is controlled per font-face:
@font-face {
font-family: 'my-font';
font-display: optional;
src: url(my-font.woff2) format('woff2');
}
🎉 Update (May 14, 2019): Google Fonts now lets you control
font loading using the display
query parameter:
<link href="https://fonts.googleapis.com/css?family=Roboto&display=optional" rel="stylesheet">
The text blocks (is invisible) for a short period*. Then, if the custom font hasn't been downloaded yet, the browser swaps (renders the text in the fallback font), for however long it takes the custom font to be downloaded, and then re-renders the text in the custom font. You get a FOIT (flash of invisible text).
*The length of the block period depends on which browser you're using. Chrome, Firefox and (recently) Safari use 3s. IE uses 0s (effectively having no block period), and older Safari used no timeout, effectively having an inifinite block period.
There is no block period (so no invisible text), and the text is shown immediately in the fallback font until the custom font loads, then it's swapped with the custom font. You get a FOUT (flash of unstyled text).
This is somewhere in between block and swap. The text is invisible for a short period of time (100ms). Then if the custom font hasn't downloaded, the text is shown in a fallback font (for about 3s), then swapped after the custom font loads.
This behaves just like fallback, only the browser can decide to not use the custom font at all, based on the user's connection speed (if you're on a slow 3G or less, it will take forever to download the custom font and then swapping to it will be too late and extremely annoying)
Side-by-side, that looks like this:
This demo simulates a slow connection speed. The font resource is returned after a 4s delay (so after the block period would normally end), so that you can see what happens for each of the options.
Very slow font (4s server delay)
Medium slow font (2s server delay)
Fast font (0s server delay)
This depends a lot on how you are using your webfont, and whether rendering the text in
a fallback font makes sense. For example, if you're rendering the main body text on a site, you
should use font-display:optional
. On browsers that implement it (all
modern browsers at the time of updating this article in 2019)
the experience will be much nicer: your users will get fast content, and if the web font download
takes too long, they won't get a page relayout halfway through reading your article.
If you're using a web font for icons, there is no acceptable fallback font you can render these
icons in (unless you're using emoji or something), so your only option is to completely block
until the font is ready, with font-display:block
.
Happy fonting! ❤️, monica