Avoid invisible text during font loading

Katie Hempenius
Katie Hempenius

Why should you care?

Fonts are often large files that take awhile to load. To deal with this, some browsers hide text until the font loads (the "flash of invisible text").

Largest Contentful Paint (LCP) can be delayed waiting for text to render. If you're optimizing for performance, you'll want to avoid the "flash of invisible text" (FOIT) and show content to users immediately using a system font, which creates a "flash of unstyled text" (FOUT).

Browser defaults for displaying fonts

These are the default font-loading behaviors for common browsers:

Browser Default behavior if font is not ready…
Chrome and Edge Will hide text for up to 3 seconds. If text is still not ready, it uses a system font until font is ready and then swaps out font.
Firefox Will hide text for up to 3 seconds. If text is still not ready, it uses a system font until font is ready and then swaps out font.
Safari Hides text until font is ready.

Display text immediately

This guide outlines two ways to display text as soon as possible: the first approach is simple and has good browser support. The second approach is in-depth, but may provide more options for you. The best choice for your website depends on your requirements.

Option #1: Use font-display

Browser Support

  • 60
  • 79
  • 58
  • 11.1

Source

font-display is an API for specifying font display strategy. swap tells the browser that text using this font should be displayed immediately using a system font. Once the custom font is ready, the system font is swapped out.

/* Before */
@font-face {
  font-family: Helvetica;
}

/* After */
@font-face {
  font-family: Helvetica;
  font-display: swap;
}

If a browser does not support font-display—though all modern browser do—the browser continues to follow its default behavior for loading fonts.

Option #2: Wait to use custom fonts until they are loaded

Browser Support

  • 35
  • 79
  • 41
  • 10

Source

With a bit more work, a more custom approach can be considered.

There are three parts to this approach:

  • Don't use a custom font on initial page load by refactoring your CSS to not use a custom fonts initially. This ensures that the browser displays text immediately using a system font.
  • Detect when your custom font is loaded using the CSS Font Loading API
  • Update page styling to use the custom font.
// Define a FontFace
const font = new FontFace("myfont", "url(myfont.woff)");

// Add to the document.fonts (FontFaceSet)
document.fonts.add(font);

// Load the font
font.load();

// Wait until the fonts are all loaded
document.fonts.ready.then(() => {
  // Update the CSS to use the fonts
});

This can also be accomplished with the FontFaceObserver library which some find an easier API to use.

This allows a number of additional considerations when loading the fonts. For example, all fonts can be loaded at once, avoiding several layouts as each font loads. Or sites could choose not to load fonts for users on slower connections, or for those using the Save Data option.

Verify

Run Lighthouse to verify the site is using font-display: swap to display text:

  1. Press Control+Shift+J (or Command+Option+J on Mac) to open DevTools.
  2. Click the Lighthouse tab.
  3. Make sure the Performance checkbox is selected in the Categories list.
  4. Click the Generate report button.

Confirm that the Ensure text remains visible during webfont load audit is passing.