7 Font Loading Strategies to Improve Your Core Web Vitals

Last updated on Oct 21st, 2021 | 16 min

When we talk about web performance and especially the Core Web Vitals (CWV), it almost seems like image and JavaScript optimization techniques steal the spotlight.

However, there is another player that shouldn’t be overlooked - web fonts.

Considering that they are often large files that take a while to load and can even block rendering of the text, font optimization is a critical piece of the overall performance strategy. 

Typography is also fundamental to good design, branding, readability, and accessibility. And web fonts are the ones making all these things possible.

In the following lines, we’ll see how fonts affect your Core Web Vitals and how you can optimize their loading.
 
Let’s begin! 

What You Should Know about Font Loading (In a Nutshell) 

There is not a single font optimization technique that can solve all of your problems. 

That might be a bit harsh, but it’s the truth. Font loading has been a big culprit of web performance for years now. And all of the current strategies for serving web fonts have significant drawbacks.

For quite some time, if you wanted to serve web fonts, you had to choose between:

  • Flash of Invisible Text (FOIT) where the text is hidden until the font is downloaded. 

Or 

  • Flash of Unstyled Text (FOUT) uses the fallback system font initially and then upgrades to the web font when it downloads.

Put simply, you could either make your visitors stare at a blank screen or risk unexpected layout shifts occurring on your website. 

Both are unacceptable solutions in today’s Core Web Vitals world.

Basically, the font loading situation was:

twitter post

Then, the font-display property was announced. 

font-display tells the browser how it should proceed with text rendering when the associated web font has not loaded. It is defined per font-face.

Browsers have default font-loading behavior when rendering text that uses a font-family that is not yet available:

Browsers default font loading behavior

Source: web.dev

The process of font downloading is divided into three major periods:

  • The first period is the font block period. If the font-face is not loaded during this period, any element attempting to use it must instead render with an invisible fallback font face (FOIT). If the font-face successfully loads during this first period, it is then used normally.
  • The font swap period occurs immediately after the font block period. If the font-face is not loaded during this period, any element attempting to use it must instead render with a fallback (system) font (FOUT). If the font-face successfully loads during this period, the font is then used normally.
  • The font failure period occurs immediately after the font swap period. If the font is not yet loaded when this period starts, it’s marked as a failed load, causing normal font fallback.

Understanding these periods will allow you to use the font-display values more effectively:

  • font-display: auto uses whatever font display strategy the user-agent uses; 
  • font-display: block gives the font a 3s (in most cases) short block period and an infinite swap period. In other words, it always swaps in the web font when it loads. Use this value when the font is important for the page;
  • font-display: swap shows the font as soon as it loads. Similar to block, this value should only be used when rendering text in a particular font is important for the page;
  • font-display: fallback hides text for up to 100ms, then only swaps in the web font if it loads within three seconds. If the font is not loaded during  the three-second swap period, the fallback will be used for the rest of the page’s lifetime;
  • font-display: optional gives the font face a minimal block period of 100ms. Then, if the font is still not available, it stays with the fallback and never swaps. Basically, the optional value leaves it up to the browser to decide whether to initiate the font download or not.

Font-display values
Source: How to avoid layout shifts caused by web fonts


When deciding which font-display value to use for your site, a good rule of thumb is this Google recommendation:

“font-display strategies reflect different viewpoints about the tradeoff between performance and aesthetics. For most sites, these are the two strategies that will be most applicable:
  • If performance is a top priority: Use font-display: optional. This is the most "performant" approach: text render is delayed for no longer than 100ms, and there is assurance that there will be no font-swap related layout shifts.
  • If displaying text in a web font is a top priority: Use font-display: swap but make sure to deliver the font early enough that it does not cause a layout shift.”

As I said earlier, there is still no complete solution that fixes all possible font issues regarding font loading. Although Google itself recommends these steps, that doesn’t mean they are risk-free.

In fact, some of the font-display values can worsen your Core Web Vitals. 

How Fonts Impact Your Core Web Vitals (CLS & LCP)

If you’re familiar with the Core Web Vitals, you probably know that some font loading methods can harm them.

For instance, if a font has not been loaded (FOIT), browsers typically delay text rendering (font-display: block). In some cases, this delays the First Contentful Paint (FCP) and the Largest Contentful Paint (LCP).

On the other hand, the practice of font swapping is well-known for causing unexpected layout shifts, which are directly related to the Cumulative Layout Shift (CLS) metric.

Now, let’s go through the font loading best practices to keep your CWV metrics in check.

Important: Although I’ve divided the following techniques based on their impact on the CWV metrics, that does not mean they aren’t best practices in general. All methods listed below can improve the overall font loading process and your site’s performance.


Avoid Layout Shifts When Loading Fonts (CLS)

Cumulative Layout Shift measures the significance of unexpected layout shifts on a page. Unexpected layout shifts occur when content on the page moves around without user input or prior notification:

Cumulative Layout shift

Two things can cause layout shifts in the process of fetching and rendering:

  • A fallback font is swapped with a new font (FOUT);
  • An “invisible” text is shown until the font is rendered (FOIT).

To attack these issues, you can implement some of the following best practices:

1) Combine link rel=preload and font-display: optional

The option to combine link rel=preload with font-display: optional has been available since Chrome 83, and it’s said to be a surefire way to avoid layout shifts.

As previously mentioned, when a font uses the font-display: optional value, it has 100ms to be downloaded and executed before the browser goes back to the fallback. 

In case that the font is downloaded before the 100ms mark, the custom font is used on the page.

That leads to the browser re-rendering the page, which in turn causes a slight flicker of invisible text.

In Chrome 83, the first render cycle is removed for optional fonts that use the link rel=preload and it’s replaced with a block period (100ms) until the custom font has loaded or the period completes. 

Now the font loading process looks like this when the font is preloaded and downloaded after the 100ms block period:

Font loading

And like this when the font is preloaded and downloaded before the 100ms mark:

Font Loading


This technique pretty much solves the problem with unexpected layout shifts and flashing of unstyled texts. 


2) Use size-adjust 

Another problem with font swapping is that sometimes when the web font loads, it shifts the entire page around since it presents at a slightly different box height size.

Putting the size-adjust descriptor in the font-face rule will lead to minimal visual change and almost a seamless swap.

Check out Google’s guide on CSS size-adjust for @font-face to learn how you can implement it. 


3) Making Your Fallback Font Match Your Web Font

To reduce the swap effect, you can try to make the fallback and the web font look as similar as possible. Of course, you cannot avoid shifts altogether, but you can try to make them less impactful so that they won’t harm the user experience as much. 

The Font Style Matcher app by Monica Dinculescu is a well-known tool for font matching.

It allows you to overlay the same text in two different fonts to see how different they are. After that, you can adjust their font settings to get them more closely aligned. 

Font overlap tool


Unfortunately, like any other font loading optimization technique, it has its risks and hurdles. 

The issue with the font style matching is that you can’t have these CSS styles apply only to the fallback fonts, so you need to use JavaScript and the FontFace.load API to apply these style differences when the web font loads.

In his lecture from 2018, Zach Leatherman explains this technique in further detail:

 


Ensure Your Fonts Load as Fast as Possible (LCP & FCP)

When it comes to font loading and improving the Largest Contentful Paint metric, the techniques we will go through are a bit more general.

LCP measures the time it takes for the largest above the fold content element to load (e.g., text, image). Everything below 2.5s is considered good LCP time:

Largest Contentful Paint

Another metric that is not part of the CWV but still could be affected by loading heavy font files is First Contentful Paint (FCP).

FCP measures the time for the browser to visualize the first piece of DOM content (e.g., text block, image, SVG, non-blank canvas element) on a page.

Both metrics measure how fast your website paints elements of the above the fold content, which play a massive role in visitors’ first impressions. 

If they stare at a blank screen for quite a while (FCP), that would not be a great user experience. The same goes for waiting too long for your largest/hero element (LCP) to render.

Optimizing your web fonts is one way to improve your site’s perceived performance and guarantee a better user experience.

Here are a couple of techniques that you might want to give a go:

1) Compress your fonts

To understand how font compression works, you need to know the anatomy of a web font.

A web font is a collection of glyphs, and each glyph is a vector shape that describes a letter or symbol. Although individual glyphs are different, they contain a lot of similar information that can be compressed.

To be able to apply the correct compression, you need to know the different font formats first:

  • Embedded OpenType (EOT) - Can be served to old IE (below I9) browsers. Not compressed by default. You can apply GZIP compression to this font.
  • TrueType (TTF) - Can be served to old Android (below 4.4) browsers. Not compressed by default. You can apply GZIP compression to this font.
  • Web Open Font Format (WOFF) - Can be served to the majority of browsers. Has built-in compression.
  • Web Open Font Format 2 (WOFF 2) - Can be served to browsers that support it. It uses custom compression algorithms to deliver ~30% file-size reduction over other formats.

Then, you can apply GZIP compression (if needed) by using an online tool or making some server configurations. 


2) Inline fonts 

In general, fonts are stored in an external CSS stylesheet. To use the stylesheet, a link is placed in the head tag of the HTML markup like this:

external css

However, running external CSS files is more time-consuming as the browser first needs to locate and then download the file. 

To speed up the font loading process, you can inline font declarations and other critical styling in the head tag of the main document rather than keeping them in an external stylesheet:

inline fonts

This will allow the browser to locate and start rendering the font faster as it doesn’t need to wait for the external stylesheet to download.

Important: Font inlining is a technique you should be careful with. Inlining large font resources or too many fonts can delay the delivery of the main document and the discovery of other resources. If possible, test how this change will affect your website’s performance before and immediately after deploying it. 


3) Make sure your fonts are downloaded quickly

It seems like a never ending debate when it comes to choosing between self-hosting fonts or relying on third parties. 

While web fonts are a great self-hosted option as they are static resources that aren’t regularly updated, relying on third-party resources is not a bad option either. 

In fact, the Web Almanac found that some sites that use third-party fonts had a faster render than sites that used first-party fonts:

third-party fonts stats


Source: HTTP Archive

At the end of the day, the most important thing is - how quickly are your fonts being downloaded and rendered? And most of the time, the answers doesn’t depend on your hosting approach, but rather on whether you have these three things in place or not: 

So instead of wasting time on questions like “Should I self-host my web fonts or not?”, make sure that you have the more important elements set up. 

4) Preconnect to third-party resources

Another technique that will allow your fonts to be loaded quickly is using link rel=preconnect.

Use the link rel=preconnect resource hint to establish an early connection(s) with the third-party origin. 

Adding link rel=preconnect informs the browser of your page’s intent to establish a connection to another domain and that you'd like the process to start as soon as possible. Resources will load more quickly because the setup process has already been completed by the time the browser requests them. 

Resource hints should be placed in the head tag of the document.

How NitroPack Can Optimize Your Font Loading and Core Web Vitals

Improving web performance can be a lot of work and headaches. That’s why using tools and services can be really helpful. 

For instance, NitroPack includes all kinds of different features that will save you a lot of time when optimizing fonts:

  • Global CDN
  • GZIP and Brotli Compression 
  • HTTP/2 Compatibility
  • Deferred loading of fonts
  • Critical CSS

Also, NitroPack allows you to configure default font rendering behavior. 

For users of the Manual mode, there's the option to override this behavior from the "Advanced Settings":

Override font rendering behavior

Furthermore, in the “Advanced settings” you will also find the option to optimize your CSS delivery:

optimize css delivery


We’re also constantly testing different font configurations to see their impact on Core Web Vitals and eventually find the best solution. In fact, this process of non-stop experimentation, along with the help of our Speed Insiders, is what allows us to offer optimal CWV results to our clients:

Core Web Vitals Tech Report 2021

And if you decide to become part of the NitroPack community, you should know that it takes no more than 5 minutes to set it up, and you can try our service with the free plan (no CC required). 
 

Niko Kaleev
Content Writer

Niko is one of the NitroPack storytellers. He is passionate about writing quality content and turning complex optimization concepts into engaging articles.