Web Fonts Performance: Making Pretty, Fast

The use of web fonts is surging. Just over the last year, the use of web fonts has doubled from ~6% to over ~12% according to the HTTP Archive. In the same time, Google Web Fonts has seen a 10x in the amount of requests, recently crossing 1B font views per day across 100M+ web pages. And there are no signs of slowdown in the adoption.

Historically, web fonts have not had a great story when it comes to performance, but this is definitely changing fast: better compression formats, improved browser handling, unicode and character subsetting, and the list goes on. Not to mention the many accessibility, indexing, translation, file size, zoom and high DPI device friendly benefits of rendering text as, well, text! To discuss this, and more, we sat down with David Kuettel from the Google Web Fonts team, for an in-depth look at web fonts.

Optimizing Web Fonts

Serving a web font is deceiving simple: download the file, put it on the local server, and we're done? Turns out, it is much more interesting than that. First, there are four different formats (woff, ttf, eot, svg), and not one of them provides universal adoption. To have a consistent experience across all platforms we have to provide multiple formats. In the long run, the goal is to have a single, well supported format, but in the meantime we have to support all the legacy browsers.

Next, the font file itself can be massive: Arial Unicode, which supports nearly all languages, weighs in at over 22MB! Of course, an average page does not need the entire unicode character set, hence we need a mechanism to restrict the font to a character subset (e.g. latin, or cyrillic only). Open Sans, which is one of the most popular Google web fonts, provides support for 20+ languages, and comes in at 217kB total, but only 36kB when restricted to latin subset. Sidenote: an average font served by Google Web Fonts today is ~35kB.

<!-- Serve Open Sans font family, but only the latin character set -->
<link href="http://fonts.googleapis.com/css?family=Open+Sans&subset=latin" rel="stylesheet" />

Next, the font file size can be further reduced by eliminating font hinting meta-data for platforms that do not support it. With that out of the way, we can apply optimized compression algorithms for a ~15% win over simple gzip compression. With WOFF 2.0 in the pipeline, we should see another 30%+ compression improvement in the foreseeable future.

Put all of these optimizations together, and it translates to 30+ static variants for each web font, custom tailored to each platform and user agent. So much for serving one file! Not to mention the dynamic optimizations, such as character subsetting, which allows you to specify the individual characters to meet your exact needs for a small headline or a similar use case.

<!-- Serve Inconsolata font family, but only provide "H", "e", "l", "o" characters -->
<link href="http://fonts.googleapis.com/css?family=Inconsolata&text=Hello" rel="stylesheet" />

Serving Web Fonts

All Google web fonts are free and open-source, which enables very effective cross-site caching: Open Sans served on this site, is the same Open Sans served across 1M+ other domains using the font. In fact, the top 40 Google web fonts are shared by 100K+ domains, and top 300 by 10K+. In other words, using a popular web font will likely translate to a browser cache hit for the font, even if this is your first time visiting my site (which uses Open Sans). The wider the adoption, the higher the likelihood of a cache hit, the better the performance!

Let's dissect a simple example of how a Google web font is served:

The CSS stylesheet provided by Google Web Fonts is a dynamic stylesheet which specifies the optimal file format for the visitors platform and browser - as determined by the combination of the optimizations we discussed earlier. This stylesheet is cached for 24 hours. Inside of the stylesheet is a URL reference to the web font resource itself. Why not inline the web font? Well, given the growing popularity of web fonts, the bet is that you already have a copy in your cache - no request is better than no request. Instead of storing N copies of Open Sans, one for each site, the browser maintains a single copy across all sites.

Leveraging the 24 hour CSS cache, and the one year cache for the web font itself allows quick and easy rollout of updates while optimizing for a fast browsing experience - vast majority of page renders will require zero requests for the fonts. The combination of a global CDN, optimized file formats, and a shared and global cache pay high dividends when it comes to performance.

Web Fonts are Here to Stay

Web fonts are here to stay, and that is a good thing - yes, even for performance. Better accessibility, zoom and high DPI friendly, optimized compression, and improved handling from all browser vendors are all working in favor of growing adoption. Not to mention the ability to combine web fonts with CSS3 for some spectacular visuals.

Having said that, serving web fonts definitely has its gotchas. If you are going the DIY route, then make sure you support all of the latest formats, optimize your fonts, serve the appropriate versions, and keep up with the latest developments - lots of things to get right! For the rest of us, a web font provider like Typekit, or Google Web Fonts is a much better bet.

Ilya GrigorikIlya Grigorik is a web ecosystem engineer, author of High Performance Browser Networking (O'Reilly), and Principal Engineer at Shopify — follow on Twitter.