A complete webFont may contain all the anamorphic fonts you don’t need, which can easily lead to Megabyte downloads. In this article, we’ll help you learn how to optimize webFont loading so that you only get the content you need.

To solve the problem of large files containing all variations, @font-face in CSS rules allows you to break up font families into collections of resources. Examples include Unicode subsets and different style variants.

Based on this declaration, this will make it very easy for the browser to calculate the subset and variation required and download the minimum set required to render the text. However, if used improperly, it can also cause performance bottlenecks in critical render paths and delay text rendering.

The default performance

Delayed font loading has a hidden effect that can cause text rendering delays: the browser must first build a rendering tree that relies on the DOM and CSSOM trees before it knows which font resources it needs to render text. As a result, font requests are delayed long after other critical resources, and browsers may not be able to render text until the resource is retrieved.

1. The browser requests HTML documents

2. The browser starts parsing the HTML response and building the DOM.

3. The browser discovers CSS, JS, and other resources and initiates requests.

4. After receiving all the CSS content, the browser builds the CSSOM and combines it with the DOM tree to build the render tree.

  • Distribute the font request after the render tree indicates which font variants are needed to render the specified text on the page.

5. The browser performs the layout and draws the content onto the screen.

  • If the font is not yet available, the browser may not render any text pixels.

  • Once the font is available, the browser draws text pixels.

The “race” between the first drawing of the page content (after the render tree is built) and the request for font resources leads to the “blank text problem” (the browser may render the page layout but ignore any text)

By preloading WebFonts and using font-display to control how the browser handles unavailable fonts, you can prevent blank pages and layout offsets due to font loading.

Preloads WebFont resources

You can use resource load priorities to pre-host a specified WebFONT on a specific URL. Use triggers requests for WebFont early in the critical render path without waiting for CSSOM to be created.

Custom text rendering delay

Although preloading makes it more likely that webFont will be available after page content is rendered, it is not guaranteed to be available. You still need to consider how the browser will behave when rendering text using a font that is not yet available.

To avoid invisible text during font loading in a web page, you can see that the browser’s default behavior is inconsistent. However, you can tell modern browsers how you want them to display by using font-display.

Similar to the existing font timeout behavior implemented by some browsers, font-display divides the font download life cycle into three main phases:

1. The first stage is font blocking. In the meantime, if the font is not loaded, any element that tries to use it must render an invisible backup font. If the font loads successfully during this time, the font can be used normally.

The font blocking phase is followed by the font exchange phase. In the meantime, if the font is not loaded, any element that tries to use it must render the backup font. If the font has successfully loaded in the meantime, use it normally.

3. The font exchange phase is followed by the font failure phase. If the font is not loaded, the browser will regard it as a loading failure, resulting in the normal font rollback. Otherwise use it normally.

Knowing these periods means you can use font-display to determine whether or when you want to load a font and how to render it.

To use the font-display attribute, add it to your @font-face rule:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  font-display: auto; /* or block, swap, fallback, optional */
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2'), /* will be preloaded */
       url('/fonts/awesome-l.woff') format('woff'),
       url('/fonts/awesome-l.ttf') format('truetype'),
       url('/fonts/awesome-l.eot') format('embedded-opentype');
  unicode-range: U+000-5FF; /* Latin glyphs */
}
Copy the code

Font display currently supports the following values:

  • auto

  • block

  • swap

  • fallback

  • optional

Font loading API

When used with font-display, you have more control over font loading and rendering without having to worry too much about overhead. But if you need extra customization and are willing to bear the overhead of running JavaScript, there is another option.

The Font Loading API provides a scripting interface to define and manipulate CSS fonts to track their download progress and override their default lazy Loading behavior. For example, if you decide you need a specific font variant, you can define it and tell the browser to start font resources immediately to get it:

var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", { style: 'normal', unicodeRange: 'U+000-5FF', weight: '400' }); // don't wait for the render tree, initiate an immediate fetch! font.load().then(function() { // apply the font (which may re-render text and cause a page reflow) // after the font has  finished downloading document.fonts.add(font); document.body.style.fontFamily = "Awesome Font, serif"; // OR... by default the content is hidden, // and it's rendered after the font is available var content = document.getElementById("content"); content.style.visibility = "visible"; // OR... apply your own render strategy here... });Copy the code

In addition, since you can check the state of a font (via the check()) method and track its download progress, you can also customize the strategy for rendering text on a page:

  • You can keep the text rendered until the font is available.

  • You can customize each font timeout.

  • You can use the fallback font to unlock the render and use the new style of the required font once the font is available.

Best of all, you can also mix and match these strategies for different content on the page. For example, you can delay rendering of some portions of text, use backup fonts first, and then re-render after the font has been downloaded and when the font is available.

Note: The font loading API is not available in older browsers. It is recommended that you consider using the FontLoader Polyfill or WebFontloader libraries to provide similar functionality, although additional JavaScript dependencies can add overhead.

Proper caching is necessary

Font resources are usually static resources that are not updated frequently. As such, they are good for setting max-ages for a long time to control expiration (make sure you specify conditional ETag headers and optimal caching policies for all font resources).

If your Web application uses Service workers, providing font resources using a cache first policy is appropriate in most cases.

Because the browser’s HTTP cache provides the best and most robust mechanism for providing the browser with font resource caching policies. So you should not use localStorage or IndexedDB to store fonts; Each of them has their own performance issues, more or less.

WebFont load manifest

  • Because the default lazy loading behavior can cause text rendering delays, you can customize font loading and rendering using, font-display, or font loading apis. These Web platform features allow you to override this behavior for specific fonts and specify custom rendering and timeout policies for different content on the page.

  • Specify revalidation and optimal caching policies: Fonts are static resources that do not update frequently. Make sure your server provides long-term max-age timestamps and revalidation tokens to allow efficient reuse of fonts between different pages. If a service worker is used, a cache first policy is most appropriate.

Automatically test WebFont loading behavior with Lighthouse

Lighthouse helps assess whether you’re following the process of Web font optimization best practices.

The following reviews can help you ensure that your pages continue to follow Web font optimization best practices over time:

  • Preload key requests
  • Uses inefficient cache policy on static assets
  • All text remains visible during WebFont loads