Skip navigation
Part I Chapter 4

Fonts

Hero image of Web Almanac characters on an assembly line preparing various F letters in various styles and shapes.

Introduction

Text is at the heart of most web sites, and typography is the art of presenting that text in a way that’s visually appealing and effective. Creating good typography requires choosing the appropriate fonts and designers have a tremendous range of web fonts to choose from. As with all resources, there are performance and compatibility concerns but, done right, the benefit is well worth it. In this chapter, we’ll dive into data to show how web fonts are being used, and in particular how they’re optimized.

Where are web fonts being used?

Web font usage has been growing steadily over time (it was near zero as late as 2011), with 82% of web pages for desktop using web fonts, and mobile at 80%.

Figure 4.1. Web font usage over time.

Usage of web fonts is fairly consistent around the world, with a few outliers. The charts below are based on the median number of kilobytes of web fonts per web page, which can be an indicator of lots of fonts, large fonts, or both.

Figure 4.2. Web fonts usage by country (desktop).

The country that uses the most font bytes is South Korea, which is not all that surprising given their consistently high internet speeds and low latency and the fact that Korean (Hangul) fonts are almost an order of magnitude larger than Latin. Web font usage in Japan and Chinese-speaking countries is considerably lower, likely because Chinese and Japanese fonts are vastly larger (the median font size can be 1000 times or more larger than the median Latin size). This means web font usage in Japan is very low, and usage in China is effectively zero. Although recent developments in progressive font enhancement–which we will cover more below–may make web fonts usable in both countries within a couple of years. There have been reports that Google Fonts have not been reliably accessible in China and that might also have been a factor holding back adoption.

Figure 4.3. Web fonts usage, top countries (desktop).

There’s an interesting thread on web font usage by country on the HTTP Archive discussion forum that certainly influenced the queries used by this chapter. Given the large number of typefaces produced for Asian languages, it’s likely usage will rise in that region as technology for serving those fonts more efficiently becomes available.

Serving with a service

70.3%
Figure 4.4. Popularity of Google Fonts amongst font-hosting services.

It likely comes as no surprise that Google Fonts remains by far the most popular platform, but the percentage use has actually dropped almost 5% from 2019 to about 70%. Adobe Fonts (formerly Typekit) has dropped about 3% as well, but Bootstrap usage has grown from about 3% to over 6% (in aggregate from several providers). It is worth noting that the largest provider for Bootstrap (BootstrapCDN) also provides icon fonts from Font Awesome, so it may be that it is not Bootstrap itself but rather older versions also referencing icon font files that is behind the rise in that source data.

Another surprise in the data is the rise in fonts being served by Shopify. Growing from roughly 1.1% in 2019 to about 4% in 2020, there has clearly been a significant uptick in usage of web fonts by sites hosted on that platform. It is unclear if that is due to that service offering more fonts that they host on their CDN, if it is growth in use of their platform, or both. However, the increase in usage of both Shopify and Bootstrap represent the largest amount of growth other than Google Fonts, making it a very noticeable data point.

Not all services have the same service

Figure 4.5. Median FCP of sites using hosted fonts.

It was interesting to note the differences in speed for sites using the various free/open source and commercial services. When looking at First Content Paint (FCP) and Last Content Paint (LCP) times, sites using Google Fonts are roughly in the middle, but generally a bit slower than the median value. The fastest sites in the dataset are Shopify and Wix (serving assets from parastorage.com), and it might be presumed they focus on a small number of highly optimized files. Google on the other hand is also serving web fonts globally of widely varying sizes (due to language), likely resulting in slightly slower median times.

Median LCP of sites using hosted fonts.
Figure 4.6. Median LCP of sites using hosted fonts.

When viewing commercial services such as Adobe (use.typekit.net) or Monotype (fast.fonts.com) it is interesting to note that on desktop they tend to be as fast or slightly faster than Google Fonts, but are noticeably slower on mobile. Conventional wisdom has generally held that the tracking scripts used by those services substantially slow them down, but that is apparently less an issue today than it has been in years past. While it’s true that we are measuring site performance and not necessarily performance of the font host, those tracking scripts impact font loading on the client so it seems relevant to include these observations.

Self-hosting isn’t always better

Self-hosting fonts on the same domain as the website can be faster, as we discovered for this very website, however this is not always the case as the data shows.

Figure 4.7. Web font hosting performance, desktop.
Figure 4.8. Web font hosting performance, mobile.

It wouldn’t be sound to infer causality between hosting strategy from the above data, as there are other variables that may confound the relationship. But, putting that aside, we find that adding the self-hosting fonts doesn’t always lead to better performance. Hosted font solutions often perform a number of optimizations (like subsetting, removing OpenType features, and ensuring the smallest possible font format) that may not always be replicated when self-hosting.

Local isn’t always better

Another option from self-hosting fonts on the site’s server, is to use the system-installed fonts on the client where they exist through the use of local in the font-face declaration. The use of local is controversial, as it can save bytes, but it can also yield bad results if the locally installed version of the font is outdated. As of November 2020, Google Fonts has moved to using local only for Roboto on mobile platforms, otherwise the font is always fetched over the network.

Racing to first paint

The biggest performance concern about integrating web fonts is that they may delay the time when the first readable text is displayed. Two optimization techniques can help mitigate those issues: font-display and resource hints.

The font-display setting controls what happens while waiting for the web font to load and is generally a trade-off between performance and visual richness. The most popular is swap, used on about 10% of web pages, which displays using the fallback font if the web font doesn’t load quickly, then swaps in the web font when it does load. Other settings include block, which delays displaying text at all (minimizing the potential flashing effect), and fallback, which is like swap but gives up quickly and uses the fallback font if the font doesn’t load in a moderate amount of time, and optional, which immediately gives up and uses the fallback font; this is used by only 1% of web pages, presumably those most concerned with performance.

Figure 4.9. Usage of font-display.

We can analyze the effect of these settings on First Contentful Paint and Largest Contentful Paint. Not surprisingly, the optional setting has a major effect on Largest Contentful Paint. There is also an effect on First Contentful Paint, but that might be more correlation than causation, as all of the modes except for block display some text after an “extremely small block period.”

Figure 4.10. font-display performance on desktop.
Figure 4.11. font-display performance on mobile.

There are two other interesting inferences from this data. One might expect the block setting to have a significant impact on FCP, especially on mobile, but in practice the effect is not that large. That suggests that waiting for font assets is seldom the limiting factor for the web page performance as a whole, though it would certainly be a major factor in pages without lots of resources such as images. The auto setting (which is also what you get if you don’t specify it) is up to the browser. It looks a lot like block because the default is blocking in most cases.

Finally, one justification for using fallback is to improve Largest Content Paint times compared to swap (which is more likely to respect the designer’s visual intent), but the data do not support this case; this performance metric is no better. Perhaps this is why the setting is not popular, used by only about 1% of pages.

Google Fonts now recommends swap in its suggested integration code. If you’re not using it now, adding it might be a way to improve performance, especially for users on slow connections.

Resource hints

While font-display can speed up the presentation of the page when the fonts are slow to load, resource hints can move the loading of web font assets to earlier in the cascade.

Ordinarily, fetching web fonts is a two-stage process. The first stage is loading the CSS, which contains a reference (in @font-face sections) to the actual font binaries.

This is especially relevant for hosted font solutions. Only after discovering the font is needed, can the connection to that server begin, which further breaks down into the DNS query for the server, and actually initiating a connection (which, these days, usually involves an HTTPS cryptographic handshake).

Figure 4.12. Resource hints use on fonts.

Adding a resource hint element in the HTML starts that second connection earlier. The various resource hint settings control how far that gets before having the URL for the actual font resource. The most common (at about 32% of web pages) is dns-prefetch, even though in most cases there are better choices.

Next we will look at whether these resource hints have an impact on page performance.

Figure 4.13. Resource hints performance, desktop.
Figure 4.14. Resource hints performance, mobile.

Analysis of this data suggests that the dns-prefetch setting, while the most popular, doesn’t improve performance much, if at all. Presumably, the DNS for popular web font servers are likely to be cached anyway. The other settings give a lot more bang for the buck, with preconnect being a sweet spot for ease of use, flexibility, and performance improvement. As of March 2020, Google Fonts recommends adding this line to the HTML source, immediately before the CSS link:

<link rel="preconnect" href="https://fonts.gstatic.com">

The use of preconnect has grown considerably since last year, now at 8% from 2%, but there’s a lot more potential performance still left on the table. Adding this line might be the single best optimization for web pages that use Google Fonts.

It might be tempting to go even farther into the pipeline, preloading or prerendering the font asset, but that potentially conflicts with other optimizations, such as fine-tuning the font for the capabilities of the rendering engine, or the unicode-range optimization described below. To preload a resource, you have to know exactly what resource to load, and the best resource for the task may depend on information not readily available at HTML authoring time.

Home on the (Unicode) range

Fonts increasingly have support for lots and lots of languages. Other fonts can have a large number of glyphs because the writing system (especially CJK) requires it. Either reason can increase the file size. That’s unfortunate if the web page is not in fact a multilingual dictionary, and only uses a fraction of the font’s capabilities.

One older approach is for the HTML author to explicitly indicate a font subset. However, that requires deeper knowledge of the content, and risks a “ransom note” effect when the content uses characters supported by the font but not by the chosen subset. See the excellent essay When fonts fall by Marcin Wichary for lots more detail about how fallback works.

Static subsets, indicated by unicode-range, are a better approach to this problem. The font is sliced into subsets, each with a separate @font-face rule that indicates the Unicode coverage for that slice with a unicode-range descriptor. The browser then analyzes the content as part of its rendering pipeline, and downloads only the slices needed to render that content.

For alphabetic languages, this typically works well although it can result in poor kerning between characters in different subsets. For languages which rely on glyph shaping, such as Arabic, Urdu and many Indic languages, static subsets frequently result in broken text rendering. And for CJK, static subsets based on contiguous Unicode ranges provide almost no benefit because the characters used on a particular page are scattered almost randomly across the various subsets. Because of these issues, correct and performant use of static subsets is tricky, and requires careful analysis and implementation.

Figure 4.15. Usage of unicode-range.

Correctly applying unicode-range is tricky, as there’s a lot of complexity to the way text layout maps Unicode into glyphs, but Google Fonts does this automatically and transparently. It is only likely to be a win for fonts with large glyph counts. In any case, current usage is 37% on desktop and 38% on mobile.

Formats and MIME types

WOFF2 is the best compression format and is now supported by effectively all browsers except for versions 11 and earlier of Internet Explorer. It is almost possible to serve web fonts using an @font-face rule with a WOFF2 source only. This format makes up about 75% of all fonts served.

Popular web font MIME types.