Web Performance Calendar

The speed geek's favorite time of year
2017 Edition
ABOUT THE AUTHOR

David Fox

David Fox (@theobto) is CTO and founder of LookZook - a company providing highly visual web performance metrics for developers and CMOs. David got his start in programming and UX as a Flash game developer during the golden age of Flash gaming (remember Newgrounds?). Since then he's applied that knowledge and transitioned to the web: becoming a Blink contributor, writer and speaker for various events like the O'Reilly Fluent conference. In his free time, David enjoys reading about psychology, cooking, playing video games, and beating his friends at poker.

Webfonts are one of the very first things we add to our sites—whether it be for individuality or stylistic reasons. Unfortunately, they are also infamous for making our sites painfully slow and frustrating to read. The end result? Frustrated users and lots of lost business opportunities. Thankfully they’ve been given lots of attention the last couple years. So let’s take a look at the three best ways for you to load your webfonts, but first let’s get everyone on the same page regarding everything that can and will go wrong with webfonts.

Three big hairy problems with webfonts

Let’s start with the two most well known issues: FOIT (Flash of Invisible Text) and FOUT (Flash Of Unstyled Text). I’m going to assume you all know how and why these issues occur with webfonts, but in case you don’t, here’s a very brief explanation: When the browser detects your usage of a custom font, it waits for your webfont to load before rendering your text (i.e., FOIT). If after ~3 seconds it has not loaded yet, it renders the text with your fallback font (usually a system font like Arial). Afterwards when the webfont is loaded, the fallback font is replaced with your webfont (i.e., FOUT). Why is this a problem? Because your webfront may have added over 2 seconds to your page’s load time, and may have lost up to 50% of your visitors.

Now for the last issue, which people don’t think about very often: Content Shifting. Ever been reading an article and 5-10 seconds into reading, the fonts change and everything on the page scrolls up? Leaving you searching for where you just were? Yeah… super frustrating and another side-effect of webfonts. This happens because the fallback font the browser used and your webfont have different metrics—the letters are wider, skinnier, shorter or taller than others. The result? All your textual content shifts up or down whenever the browser switches back to using your webfont. Ewww.

Font loading methods

Now that we know the three problems, let’s look at the three font loading methods you can use to avoid these problems altogether.

The Amazon Way – Simple and sweet

Amazon knows very well the detriments webfonts can bring to your site, so they devised a devilishly simple, but effective font loading technique removing FOIT, FOUT and content shifting. Here’s their method:

  1. Start out by loading your page using only system fonts. Effectively killing FOIT.
  2. Later into the page load, make an asynchronous request for the webfont so the browser caches it on disk for future use. They achieve this using their own custom libraries but you can achieve something similar using fetch or libraries like https://github.com/bramstein/fontfaceobserver
  3. After the async request has completed, they set a localStorage object indicating the font “should” now be cached on disk (see below).
    Amazon font state in localStorage
  4. On the next page load, an inlined piece of JS checks if this localStorage object is present. If it is, the JS sets a class on the body object enabling use of the custom webfont. Since on this second page load the webfont “should” be cached, when the webfont is now used there is no flash of unstyled text and thus no content shifting 😀.

So what’s the downside to using this method? Its heavy reliance on browser disk cache not being flushed. Unfortunately, according to some older research, iOS devices remove browser disk cache very aggressively… which means you’ll run into instances where localStorage indicates the font is cached, but the device has already wiped it.

font-display: optional; The way of the future

It’s not only Amazon who has been working to make webfonts better, but the standards committee as well! And after years of work and discussion, we now have a brand new CSS property giving you control over how the browser handles the loading of your webfonts: font-display.

This is a topic I could easily write an entire article on, so to keep this brief, I’d like to point you to a section of a presentation by Monica Dinculescu (@notwaldorf) that will tell you almost everything you need to know https://vimeo.com/241111413#t=1065 (or if you prefer reading, check out https://developers.google.com/web/updates/2016/02/font-display).

As you’ll see there are many different options, but I highly recommend using the optional setting which tells the browser to do the following: Only use the webfont if it is available immediately. Otherwise, use the fallback font until the next page view. This prevents the browser from waiting for your webfont (no FOIT), or swapping it out mid page view (no FOUT or content shifting).

Alright sounds great, but what’s the catch? There’s two of them:

  1. Only ~50% (USA stat, better if looking worldwide) of mobile browsers have support for this feature—which is where it matters most: https://caniuse.com/#feat=css-font-rendering-controls
  2. This property cannot be added to a given element like html; it must be added to the @font-face tag. What’s this mean for you? If you’re using something like google fonts, which most do, you’ll have to manually create and edit the @font-face css. Challenging? No. Tedious? A bit 😐

localStorage; Taking matters into our own hands. My fav

Just like Amazon, sites like The Guardian take font loading very seriously and have devised their own solution to the three problems. Here’s their process:

  1. Download the webfonts you are using to your local machine, base64/JSON encode them, and upload them back to your server. Name the files something like Roboto.json
  2. Like all the other methods, so we avoid FOUT, the first view of our page uses no custom fonts.
  3. Just like Amazon’s method, mid-way into the page view we will asynchronously fetch the base64/json encoded fonts we uploaded and save them in localStorage (see below). This might sound like a lot of data to store… but even 2-3 fonts encoded in this manner tend to stay under 100kb in size.
    The Guardian encoded font in localStorage
  4. Now that we have our font stored, on future page loads we can check for the presence of this localStorage object, and if it exists, inject and inline the font in a style tag with JS.
  5. After we detect the font has been injected, we simply add a class to the body object (just like the “Amazon” method) indicating our webfont is now available.

So what’s the big difference between The Guardian’s method and Amazon’s? Since we are storing the actual font in localStorage and then inlining it, we never have false positives regarding the presence of our webfont. Plus, as a nice added bonus, your page is now able to use this font offline as well. The one major downside to this though, is the amount of time and instrumentation required to pull it off.

Conclusion

So which method should you use to load your webfonts? Unfortunately the answer is it depends:

  1. If you’re looking for a quick and simple method you can have working within an hour, use Amazon’s method
  2. If you want something a bit more thorough and are alright with the limited browser support for now, try using font-display: optional
  3. And if you really want to make an effort to optimize your webfont loading, take the dive and look into the localStorage technique

But regardless of which you choose, you can now be happy that you’re now the webpage on the right 😋 (see below):

Normal font vs font-display: optional

Other notes and links I didn’t have time to write about:

  1. https://meowni.ca/font-style-matcher/. If you can’t put up with your page using a fallback font its first view (if your font isn’t available yet) and want to always swap it out… this tool will help you edit your fallback font’s metrics to be much more similar to your webfonts’ and help minimize content shifting.
  2. Need help finding what system fonts you can use as fallback fonts? Use https://www.cssfontstack.com/ to look through the fairly large amount of widely available system fonts you can choose from.