Zach’s ugly mug (his face)

Zach Leatherman

The Web Fonts: Preloaded

April 05, 2016 #12 Popular

Summary: If you’re not currently using a font loading strategy, using preload with web fonts will reduce the amount of FOIT visitors will see when they visit your site—paid for by sacrificing initial render time. Don’t preload too much or the cost to initial render will be too high. For devs using a font loading strategy, the same rules apply. Try to only preload a single web font, whether that be the only font in a single stage load or the subset font in the first stage of a two stage load. Further, preload is an improvement over Data URIs for two stage font loads in supporting browsers, and I will be happy to welcome it as a best practice when its browser support grows.

After the recent release of loadCSS 1.0 updated the utility into a <link rel="preload"> polyfill for CSS and Yoav Weiss’ excellent Smashing Magazine post on preload, I decided to experiment with preload to see if it could improve the variety of web font loading approaches I’ve written about in the past.

Here’s all you need to add to the <head> of your page to start preloading:

<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

via Preload: What Is It Good For? by Yoav Weiss

If you have WOFF2 formats in your @font-face block, make sure you preload the WOFF2 format. In fact, you should probably limit preload to the first format in your @font-face src stack. If you preload a WOFF file and have WOFF2 first in your stack, the browser will download both. This is undesirable.

Benchmarks #

Let’s look first at the effect of preload on my own site without any font loading strategy:

(Times generated using Chrome Canary’s Developer Tools Network Throttling in Regular 3G mode)

With <link rel="preload">
No PreloadPreload Romanand Preload Italicand Preload Boldand Preload Bold Italic
Initial Render573ms795ms
Roman Loaded2.12s888ms
Italic Loaded2.12s1.83s
Bold Loaded2.20s1.96s
Bold Italic LoadedN/AN/AN/AN/A1.63s

Perhaps obviously, the more fonts you preload the more initial render time suffers. It’s even more interesting when you compare to the numbers I ran on Data URIs.

(Times generated using Chrome Canary’s Developer Tools Network Throttling in Regular 3G mode)

Compare preload with Data URI
Default BehaviorInline Roman Data URIPreload Roman
Initial Render573ms953ms795ms
Roman Loaded2.12s1.01s888ms
Italic Loaded2.12s2.05s1.83s
Bold Loaded2.20s2.11s1.96s
Bold Italic LoadedN/AN/AN/A

preload affects initial render less than Data URIs and from a maintenance perspective it operates much cleaner. preload improves the performance of all four drawbacks on listed on the Data URI post:

  1. They don’t directly block render, although as shown above in low bandwidth situations they can delay initial render.
  2. You can add a type attribute to declare the font format to download. Right now only Chrome Canary has a working implementation of this feature and it also supports WOFF2. But this type attribute protects you if a browser implements preload without a newer font format (or vice versa).
  3. Works great with browser cache.
  4. Multiple preloaded fonts load in parallel (although I wouldn’t recommend preloading multiple web fonts).

Best Practice? #

If the alternative is doing nothing (please don’t), then yes I would recommend preloading the most often used web font on your site. In the example above, Lato-Regular.woff2 was 25KB. If you preload more file weight (or more fonts), the tradeoff in initial render time might make it more difficult to accept.

Use with a Font Loading Strategy #

preload isn’t a panacea because it’s not sufficient by itself as a font loading strategy. There are two major considerations to font loading: (1) Eliminating the Flash of Invisible Text (FOIT) by showing a Flash of Unstyled Text (FOUT) and (2) Speeding up font loading to minimize the amount of time that fallback text is shown. We want to reduce the jarring reflows that happen when content is re-rendered with our new, shiny web fonts. An ideal strategy would eliminate both FOIT and FOUT.

preload helps our second point but does nothing for the first. We still need to implement a FOUT strategy—of course, my favorite is still Critical FOFT with an inline Data URI for the first stage. This strategy has shown to eliminate FOIT and FOUT, but at a cost documented above (and in the Data URI post). Let’s see how preload plays out there:

(Times generated using Chrome Canary’s Developer Tools Network Throttling in Regular 3G mode)

2-Stage Font Loading Strategies
Critical FOFTCritical FOFT Roman Data URICritical FOFT preload
Initial Render588ms
Stage 1 Render
(Critical Roman)
Stage 2 Render
(Roman, Italic, Bold, Bold Italic)

The results are pretty good for a Two Stage font loading approach. If your web font requirements are a little simpler and you’re only loading a single web font (One Stage font loading), then preload will have a similar beneficial performance gain. However, if you’re loading multiple web fonts in a grouped load (again, One Stage) with a single repaint/reflow step, preload isn’t wise: if you preload one of the fonts, the repaint/reflow will not happen until all web fonts have completed and it will be wasted; if you preload all of them, the sacrifices to initial render are too costly.

Conclusion #

The benefits to preload for fonts are numerous—especially over the Two Stage Data URI approach. The only nail in the preload coffin now is browser support. Once browser support for this is better, I will definitely switch from using Data URIs in the first stage of Critical FOFT to simply preloading the hosted first stage WOFF2 file (or similarly if you’re only loading a single web font). Always measure the sacrifice in initial render time to determine if this trade-off is worth it for your site.

Retweet to share this post

Zach’s ugly mug (his face)

Zach is a builder for the web with Netlify. He’s currently fixated on web fonts and static site generators. His public speaking résumé includes talks in eight different countries at events like Beyond Tellerrand, Smashing Conference, CSSConf, and The White House. He is an emeritus of Filament Group, NEJS CONF, and still helps out with NebraskaJS. Read more about Zach »

Web Fonts for President 2016
Trying out a new Font Stack
3 Replies
    1. Richard Fink Disqus

      24 Jun 2016 at 09:17AM
      Like your advice, Zach. You don't hedge. "Try to only preload a single web font"Clear advice. Thanks.
      1. robertmodel Disqus

        07 Jun 2017 at 10:40PM
        whats the deal with the menu explosion? trying to hint someting?
        1. zachleat Disqus

          08 Jun 2017 at 03:09PM
          what’s the deal with airline food??
        3 Mentions
        1. Ou … Comment je me suis rasé ~ 33 secondes sur le chargement de ma page en corrigeant les polices 20 mars 2020 Il y a quelque temps, j’ai pu raser environ 33 secondes après le temps de chargement de ma page en fixant la façon dont je charge les polices. Rasé ~ 33s à partir de … Truncated

        2. #

        3. #