"Ensure text remains visible during webfont load" In Lighthouse oplossen.

"Ensure text remains visible during webfont load" in short

When loading an (external) web font, the text on a web page will be temporarily hidden until the web font has been loaded. This can reduce the user experience. 

Solve this by adjusting the font display value of the font or by using a font loader. I will tell you how this works in this article.

Critical request chain example

Make sure that the text remains visible while loading web fonts

Web fonts are usually large files and can take a while to load. Most browsers hide the text on the page until the web font is loaded. This creates a Flash Of Invisible Text the moment the invisible font is replaced by the web font.

Ensure text remains visible during webfont load

Do you load a webfont on your page with this Flash Of Invisible Text? Then while analyzing the pagspeed on lighthouse you will get the message: "Ensure text remains visible during webfont load". Behind this is how much time you can save by making text visible before the web font is loaded. For a single font that is quickly 100ms.

Why is invisible text bad for page speed?

Ensure text remains visible during webfont load

Why would you want text to remain visible while loading a web font? You do that for your user. You don't want to make your user wait too long and you don't want to make them stare at an empty page. That is why it is smart to start showing text anyway while loading a web font. This way the visitor gets the idea that your page does respond super fast.

A quick reminder: ERROR AND ERROR

Before we continue it is useful to be able to distinguish the following concepts of god. The FOIT stands for the Flash Of Invisible Text and occurs when web fonts are not visible during loading. You can overcome this by adding a fallback font. When the fallback font is replaced by the web font you speak of the ERROR, the Flash Of Unstyled Text.

Make web fonts visible during loading

There are 2 ways to make web fonts visible during loading. The first is through the CSS font display value and the second is by using a fallback font through a class. Both methods have advantages and disadvantages. I will discuss them below.

Methode 1: Font-display:swap

The font display descriptor determines how a font is displayed based on if and when it is downloaded and ready to use. font display is a CSS property available in most of the latest updated browsers. font display is used in a @ font face. When we set the font-display: swap setting, when the page is first loaded, the system default fonts are swapped unless the custom fonts or Google fonts are loaded. This helps the user to read the content immediately.

Google fonts

If you are using google fonts embedded in the website using standard or @import as below then you can simply add "& display = swap" at the end to fix the problem.

<!-- via een extern stylesheet -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
<!-- via de import methode -->
<style>
 @import url ('https://fonts.googleapis.com/css?family=Open+Sans&display=swap); 
</style>

Local fonts

Are you using local fonts (okay, that's a lot faster than Google fonts). Then you can add font-display: swap to the font-face declaration yourself.
@font-face { 
 font-family: "Open Sans";  
 font-weight: 400; 
 font-style: normal; 
 src: url("OpenSans400.woff2") format("woff2"); 
 font-display: swap
}

Method 2: Fonts with a class

The second way to make fonts visible during loading is to work with classes. These classes are usually (but not always) given to the <body> or <html> element.
The advantage of this method is that you have more control over the fallback font and the timing of the Flash Of Unstyled Text.

This method works as follows: in your stylesheet you indicate that a page may initially be rendered with a font (the fallback font). Then you load the web font via the JavaScript fontface API or via preloading. After this font has been loaded, add a class to your page. This class ensures that the web font is activated.

Why would you do that you might ask? You do this to get more control over the fallback font. You can display the fallback font with a larger line spacing or a different size so that it better matches the web font. This prevents layout shifts.
If you use multiple web fonts, you can have all fonts switched at once via the fontface API method. That saves a lot of re-paints for a browser. Personally, I am not a fan of the latter method. This also ensures that the ERROR only happens after the last font has been loaded. That is always later than necessary.

Font with a class via the FontFace API:

The first way to use fonts with a class is through the FontFace API. YOU load the web font via JavaScript and once the font is loaded add a class.
<style>
  //fallback font met een .9rem font-size
  html{
    font-family: sans-serif;
    font-size:.9rem;
  }  

  //webfont font met een 1rem font-size
  html.fl{
    font-family: 'webfont';
    font-size:1rem;
  }
</style>

<script>
var font = new FontFace("webfont", "url(/font.woff2)", {
  style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});

// don't wait for the render tree, initiate an immediate fetch!
font.load().then(function() {
  document.fonts.add(font);
  document.documentElement.classList.add("fl")
});
</script>

Via a preload link

The second method is through a preload link. Preload the font as described below and once this is done switch the class of the <html> element.

<link 
  rel="preload" 
  href="/webfont.woff2" 
  as="font" 
  type="font/woff2" crossorigin
  onload="document.documentElement.classList.add('fl')">

<style>
  //fallback font met een .9rem font-size
  html{
    font-family: sans-serif;
    font-size:.9rem;
  }  

  //webfont font met een 1rem font-size
  html.fl{
    font-family: 'webfont';
    font-size:1rem;
  }

  //fontface, wordt pas geactiveerd zodra de .fl class wordt toegevoegd aan de html tag
  @font-face{
    font-family:'Open Sans';
    font-style:normal;
    font-weight:400;
    font-display:swap;
    src: url(/webfont.woff2) format("woff2");
    unicode-range:U+000-00FF;
  }
</style>

Extra tips on tricks

  1. Preload visible fonts. By default, fonts are not downloaded until a font is used. Are you sure you need a web font? Then preload it so that it is available sooner.
  2. Do you want to prevent FOIT and FOUT completely? Use font display: optional in combination with preloading.
  3. Hosting WebFonts yourself is always faster than web fonts via Google fonts or another external CDN.