The Web Fonts: Preloaded
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>
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)
No Preload | Preload Roman | and Preload Italic | and Preload Bold | and Preload Bold Italic | |
---|---|---|---|---|---|
Initial Render | 573ms | 795ms (+38%) |
980ms (+71%) |
1.23s (+114%) |
1.38s (+140%) |
Roman Loaded | 2.12s | 888ms (-138%) |
1.18s (-44%) |
1.42s (-33%) |
1.75s (-17%) |
Italic Loaded | 2.12s | 1.83s (-13%) |
1.10s (-48%) |
1.33s (-37%) |
1.56s (-26%) |
Bold Loaded | 2.20s | 1.96s (-10%) |
1.92s (-12%) |
1.46s (-33%) |
1.75s (-20%) |
Bold Italic Loaded | N/A | N/A | N/A | N/A | 1.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)
Default Behavior | Inline Roman Data URI | Preload Roman | |
---|---|---|---|
Initial Render | 573ms | 953ms | 795ms (-16%) |
Roman Loaded | 2.12s | 1.01s | 888ms (-12%) |
Italic Loaded | 2.12s | 2.05s | 1.83s (-10%) |
Bold Loaded | 2.20s | 2.11s | 1.96s (-7%) |
Bold Italic Loaded | N/A | N/A | N/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:
- They don’t directly block render, although as shown above in low bandwidth situations they can delay initial render.
- 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 implementspreload
without a newer font format (or vice versa). - Works great with browser cache.
- 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)
Critical FOFT | Critical FOFT Roman Data URI | Critical FOFT preload |
|
---|---|---|---|
Initial Render | 588ms |
619ms (+5%) 65.7KB HTML |
675ms (+14%) 58.6KB HTML |
Stage 1 Render (Critical Roman) |
1.04s | 619ms (-40%) |
675ms (-35%) |
Stage 2 Render (Roman, Italic, Bold, Bold Italic) |
2.57s | 2.44s (-5%) |
2.29s (-10%) |
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.
3 Comments
Richard Fink Disqus
24 Jun 2016robertmodel Disqus
08 Jun 2017zachleat Disqus
08 Jun 2017