Solving "Ensure text remains visible during webfont load" in Lighthouse.
"Ensure text remains visible during webfont load" in short
Webfonts are fonts that aren’t available by default for use on a web browser. What you get is that webfonts have to be downloaded before they can be used. While downloading a webfont, the text on a webpage is temporarily hidden until the webfont has been loaded.
As a result, it will seem like the page loads a lot slower because the page hasn’t “finished” loading for visitors to use. This could lead to a reduced user experience. When you run a Lighthouse analysis on your page, a warning about the page load performance appears: "Ensure text remains visible during webfont load".
Solve this by changing the font-display value or by using a font loader. I explain how this works in this article.
Make sure that the text remains visible while loading webfonts
Before webfonts existed, web designers were stuck with just a small number of pre-installed fonts. Webfonts give you the freedom to use any font on a website.
Of course that sounds nice, but webfonts also have their disadvantages; they slow down the loading page speed in several ways.
Webfonts are usually large files which are not installed on a computer by default. So webfonts must be downloaded before they can be used. While downloading a webfont, the text on a webpage will be temporarily hidden until the webfont has been loaded completely. This makes for a poor user experience; nobody wants to stare at an empty screen for too long.
As soon as the webfont is loaded and rendered, the browser replaces the “invisible text” for the final text with the new webfont. This moment is called the Flash of Invisible Text (FOIT). This FOIT is what causes the "Ensure text remains visible during webfont load" error message to appear..
Loading a webfont on your page and not taking any precautions to prevent this Flash of Invisible Text? While you analyze the PageSpeed on Lighthouse, the following message will appear: "Ensure text remains visible during webfont load". This tells you how much time you could save by making the text visible before the webfont is loaded. For 1 single font, this is easily 100ms.
Why is invisible text bad for page speed?
Invisible text won’t really slow down the final measured loading time of a page. So why does Lighthouse think it's such a problem?
Google thinks it’s important a web page provides the best user experience possible. The user experience can be improved by showing content on the page as fast as possible. Compare the two filmstrip versions of our homepage below:
Flash of Invisible Text
No flash of invisible text with display:swap
As you can see, the two pages finished loading at exactly the same time. Still, the latest version of the website looks a lot better to visitors. Visitors can start reading immediately.
That's why it's smart to show text anyway - not in the final font, but in a “fallback” font. This way the visitor thinks your page really does load superfast.
A brief reminder: FOIT and FOUT
Before we go any further, it’s helpful to distinguish the following concepts: FOIT and FOUT. FOIT stands for the Flash of Invisible Text and occurs when webfonts are not visible during loading. You can mitigate this by including a fallback font. When the fallback font is replaced by the webfont, it is called FOUT, Flash of Unstyled Text.
Make webfonts visible during loading
Tgere are two ways to make webfonts visible during loading: first is via the CSS font-display value; second is by using a fallback font via a class. Both methods have advantages and disadvantages, which I will discuss below.
Method 1: Font-display:swap
Font-display is a CSS descriptor that is available to all modern browsers. The font-display descriptor determines how a font is displayed based on if and when it was downloaded. Font-display is used in a @font-face rule.
There are different font-display values: block, swap, fallback and optional. Use the swap value to avoid FOIT, and to have the text appear on the screen as fast as possible, use the swap value.
Once we set the font-display: swap value in the @font-face rule, the system's default fonts are used while the page loads until the webfonts have been loaded. This helps the visitor read the text on the page immediately.
Google fonts
When using Google fonts, you can use the font-display: swap method with a simple “&display=swap” in the stylesheet or embed code.
<!-- 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>
By the way, we’re not fans of Google fonts. It’s almost always much faster to host webfonts yourself. It gives you more control over the “preloading” process of the fonts. You can use the already existing http/2 connection and you don't have to download an extra stylesheet.
Local fonts
@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) added 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 or Unstyled Text.
This method works as follows: Indicate in your stylesheet that a page should initially be rendered with a font (the fallback font). You then load the webfont via the JavaScript FontFace API or via preloading. After this font has been loaded, add a class to your page. The class makes sure the webfont is activated.
Why would you do that, you might ask? You do this to gain more control over the fallback font. You can display the fallback font with a larger line spacing or a different size so it matches the webfont better. This prevents layout shifts.
When using multiple webfonts, you can use the FontFace API method to switch all fonts at once. This saves a lot of browser repaints. Personally I am not a fan of this method; this ensures that FOUT takes place after the last font has been loaded. So that is always later than necessary.
Font with a class via the FontFace API:
<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 via a preload link. Preload the font as described below. 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 and tricks
- Always preload https://www.corewebvitals.io/nl/pagespeed/ensure-text-remains-visible-during-web font-load? visible fonts. Fonts are not downloaded by default until a font is used. Sure you need a webfont? In that case, preload it so it’s available sooner.
- Want to avoid FOIT and FOUT entirely? Use font-display: optional in combination with preloading.
- Hosting webfonts yourself is always faster than webfonts via Google fonts or another external CDN.
Stop Guessing, Start Measuring
I use Core/Dash to optimize my clients sites. So Should You.
- Easy set up.
- Over 5000 happy clients
- Free trial, No strings attached