When users visit our website for the first time, if the website uses Web fonts, they usually need to download all Web fonts.

In most cases, the Web font file may still be being downloaded after the HTML file has been loaded in the browser.

In this case, the browser cannot use Web fonts yet. So what should we do?

There are usually two options:

  1. Wait until the Web font has been downloaded before displaying the text.
  2. Render text using a backup font, that is, a font installed locally on the user’s device.

But both approaches bring new problems. The first method has the problem Of FOIT — Flash Of Invisible Text. The second method, however, will have FOUT — Flash of Unstyled Text.

The above problems may not seem familiar to you. This could be:

  • Fonts are already installed on your device
  • Your network environment is already fast
  • These problems usually occur only the first time a page is accessed, because the browser has already cached the font files, so they won’t occur again

This problem will exist as long as users need to download Web fonts the first time they visit our pages. Fortunately, however, we can improve things with some modern CSS.

The font – the display properties

To control how fonts should be rendered before they are available, we can use the font-display property.

It’s included in our @font-face declaration:

@font-face {
  font-family: 'Great Vibes';
  src: url('/fonts/great-vibes.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap; / * 👈 👈 👈 * /
}
Copy the code

When we add the Google Font snippet, it contains a query parameter to set this property:

To understand this property, we need to discuss the font-display timeline.

When the browser renders an HTML element using a Web font, a timer starts. This timer has three phases:

  • The block period during which The text is not visible and The browser renders The text once The Web font has been downloaded.
  • The swap period, when browsers use backup fonts (i.efont-familyRender the text, and replace the backup font text with the Web font once the Web font download is complete
  • The failure period, when The browser stops trying to load fonts if they are not complete during blocking or swapping, and displays backup fonts even after downloading and loading Web fonts

How long is each period? This depends on the font-display property. In effect, font-display is a way of controlling the length of each window.

Let’s take a look at the options:

Block

font-display: block; Font availability is put first, it has a relatively long time period and an infinite exchange period.

This property does not provide an explicit time duration for these periods in the CSS specification, but does provide the maximum recommended value. For font display: block, the block period should not exceed 3 seconds.

Blocks should be used when fonts are absolutely important. With an icon font, for example, if the icon font is not loaded and the text is displayed, the user may see random letters instead of ICONS.

Swap

Using font-display: swap has almost no blocking cycles and has an infinitely long swap cycle. The goal is to get the rendered text as quickly as possible.

This is how Google Fonts works. This is a good choice, but in most cases there is a better choice, a fallback.

Fallback

Font-display: fallback is the most complex, with a very short blocking cycle (about 100ms) and an appropriate switching cycle (about 3s).

It has the best user experience:

  • On high-speed networks, fonts can be downloaded during blocking cycles, which can avoid blinking fonts.
  • In the event of a bad network, an alternate font will be used to prevent blinking after a page has finished loading.

Optional

Finally, font display: optional is also a good choice for loading fonts that are not particularly important but have minor improvements. It is characterized by a short blocking cycle (100ms or less) and no switching cycle. If the font does not load immediately, it will not be used.

In general, using optional means that the user will see the alternate font for the first time, with no page flicker. But subsequent pages will use Web fonts. Because the Web font is already loaded when you first visit the page.

That’s the difference between different values of the font-display property.

Font matching

If you use a font-display attribute with a swap cycle (except optional), the rendered text will undergo a conversion process, which can result in unpleasant layout offsets if the font between the two conversions is very different, as shown below:

One possible solution is to use attributes such as font-size/letter-spacing/line-height to make the two fonts as close as possible.

The following is the adjusted effect:

“Font Style Matcher” is a beautiful tool created by Monica Dinculescu that helps you find the CSS you need to match these two fonts:

The tricky thing is that we need these declarations to only apply to our fonts before they load. There is no such method in pure CSS, but it can be implemented in JS using the Font Loading API.

Browser vendors are actively developing a new feature called “font Descriptors” (also known as F-MoDs). This allows us to adjust the characteristics of the backup font to match the Web font for a more natural font conversion. Here’s how this feature is used:

@font-face {
  font-family: "Great Vibes";
  src: url('/fonts/great-vibes.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Fallback";
  size-adjust: 95%;
  ascent-override: 90%;
  descent-override: 120%;
  src: local("Arial");
}
body {
  font-family: "Great Vibes"."Fallback", sans-serif;
}
Copy the code

The Fallback in the second font-face declaration does not refer to the actual font but to the font in SRC. Local: obtains the Web font locally.

Size-adjust is used to adjust the font size. Ascent – Override and Descent – Override are used to change the line height, which is the baseline height adjusted by changing the line-height attribute.

However, these attributes are not currently widely supported. Size-adjust can only be used in Chrome and Firefox development versions, not in other browsers. In the future, though, it could be a low-cost way to improve the font loading experience.

How to Avoid Layout shifts by Web Fonts