Grow your CSS skills. Land your dream job.

Preventing the Performance Hit from Custom Fonts

Published by Chris Coyier

The issue is 1) custom fonts are awesome and we want to use them 2) custom fonts slow down our pages by being large additional resources. Dealing with this has been in the air recently so I thought I'd round up some of the ideas and add thoughts of my own.

Only load on large screens

The first idea I saw was Dave Rupert's tests on only loading @font-face on large screens. Turns out if you use @font-face but don't ever apply that font-family, the font won't be downloaded. Pretty smart, browsers. Dave's demo.

@font-face {
  font-family: 'Dr Sugiyama';
  font-style: normal;
  font-weight: 400;
  src: local("Dr Sugiyama Regular"), local("DrSugiyama-Regular"), url(http://themes.googleusercontent.com/static/fonts/drsugiyama/v2/rq_8251Ifx6dE1Mq7bUM6brIa-7acMAeDBVuclsi6Gc.woff) format("woff");
}

body {
  font-family: sans-serif;
}
@media (min-width: 1000px) {
  body {
    font-family: 'Dr Sugiyama', sans-serif;
  }
}

Jordan Moore has an article on the Typekit Blog "Fallback Fonts on Mobile Devices" that uses the same thinking.

I applied this thinking to my own project by producing two separate font kits: a “full” font kit containing all the typographical styles I originally intended to use, and a “light” kit containing fewer fonts (and, consequently, weighing significantly less). I loaded the kits via JavaScript depending on the width of the user’s screen, with the value based on the smallest breakpoint.

With Dave's technique, you wouldn't have to worry about FOUT (Flash of Unstyled Text) since it's using native @font-face and most browsers have dealt with that. Jordan's technique would be more subject to FOUT I would think, having to load the fonts after a test, but you could fix that how you always fix that with Typekit: using visibility: hidden while the fonts load.

Ajax in the fonts

If your biggest concern is slowing down the render time (not necessarily the fully loaded page time), you could Ajax in the stylesheet that contains the @font-face stuff after document ready. Omar Al Zabir has a tutorial on this. (thx Kevin)

$(document).ready(function(){
  $.ajax({
    url: fontFile,
    beforeSend: function ( xhr ) {
      xhr.overrideMimeType("application/octet-stream");
    },
    success: function(data) {
      $("<link />", {
        'rel': 'stylesheet'
        'href': 'URL/TO/fonts.css'
      }).appendTo('head');
    }
  });
});

Making sure the font files have far expires headers is important too. In order to beat FOUT here, you would add a class to the <html> element (immediately with JavaScript) that you would use to visibility: hidden what you want to hide until the fonts load, and remove it in the Ajax success callback.

Lazy load the fonts, load on subsequent page loads after cached

Extending that idea, perhaps we could only display custom fonts if we were pretty darn sure the font files were cached. On the back-end, we check for a cookie (that we'll set ourselves later) that indicateds the fonts are cached.

// Check if cookie exists suggesting fonts are cached

if (fonts_are_cached) {
  echo "<link rel='stylesheet' href='/URL/TO/fonts.css'>";
}

On the front-end, we'll do the exact opposite. If the cookie isn't there, we'll lazy-load those fonts and then set the cookie.

// Check if cookie exists suggesting fonts are cached

if (!fonts_are_cached) {

  // Don't slow down rendering
  $(window).load(function() {

    // Load in custom fonts
    $.ajax({
      url: 'URL/TO/font.woff'
    });
    $.ajax({
      url: 'URL/TO/font.eot'
    });
    // Don't actually do anything with them, just request them so they are cached.

    // Set cookie indicating fonts are cached

  });
  
}

Not foolproof, since that cookie isn't 100% proof that font is cached. But if you set it to expire in like one day it stands a decent chance. No FOUT here though, since it either doesn't load the fonts at all or does it natively with @font-face. If you don't mind FOUT (i.e. you want to show your custom font on that first page load no matter what), you could create the <link> and insert the fonts stylesheet instead of just requesting the fonts.

Another alternative would be to place a data URI version of the font into localStorage and yank it out when you need it. You would create a <style> element, put the @font-face code in that using the data URI version of the font, and inject that. Apparently The Guardian is trying that.

Fair warning, localStorage can be slower than cache.


A possible advantage to using JavaScript fanciness is knowing which font versions you need.

And how.

The Future

This all gets better the more information we can get our hands on regarding the clients situation.

What kind of bandwidth and latency are they getting? This is pretty hard (and heavy) to test and not super reliable even when we can. Perhaps the network information API will help someday.

What is their screen size? What are the capabilities of the browser? We can test this stuff in JavaScript, but what if it would be better to know server side? Perhaps Client-Hints will help someday.

Comments

  1. Permalink to comment#

    Web fonts do get cached, right? So it’s only an issue on initial load?

  2. Permalink to comment#

    With your lazy load method… either I’m missing something or the whole first page view is one big ‘FOUT’. Maybe that’s what you mean with ‘awkward’ though.

    • Maciek
      Permalink to comment#

      No, the whole first page won’t have custom fonts. Nice fonts appears when you refresh site, or go to any subpage. I’m i right?

  3. Permalink to comment#

    Wish I could learn Javascript much faster :)

    • Kobe
      Permalink to comment#

      check out codecademy.com, they have great free javascript and jquery learning tracks

  4. Another quick tip: If you’re hosting the font files, they can also be gzipped (except for the WOFF format), with a size savings of 40-70%. See Gzip your @font-face files and @font-face and performance for more details.

  5. The Ajax method is pure “flossin”…

    Define “flossin”: showig off an object in which usually posesses great value (Urban dictionary).

    I don’t know much – but I think the “media query” method is sufficient… even in South Africa #seriously.

  6. Vinod Dalvi
    Permalink to comment#

    Very useful article.

  7. Agree with @Archie Makuwa. I think the “media-query” solution is the simpliest and reliable solution. I wish we could use bandwidth media-queries! http://css-tricks.com/bandwidth-media-queries/

  8. Permalink to comment#

    For me the width based media query method is just wrong. Device size is a very poor indicator of bandwith, plus on my desktop I have an average screen.

    On my Nexus 4 I have a beautiful HDPI screen and on my iPad I have a retina screen – so which devices do I want super sharp beautiful fonts on? – the very ones which could be excluded by media queries.

    IMHO we have got to (and I’m sure we will) get to a point where we can reliably detect the user’s connection speed – the NetworkInformation and Connection interfaces look promising if a bit distant.

    Until we actually know how fast a user will download the data we are sending them we can’t optimise their experience – the best route for now is to optimise for everyone by making pages as light as possble for all scenarios.

    This is a far bigger issue for responsive images than for fonts as we can’t cache as effectively for a fast site wide experience.

    Oh for “media all and (min-speed: ~1Mbps) {}” etc!!

    For now if a client’s site is very speed dependant (hopefully backed up by solid analytics data and user research) I just use websafe fonts, boring but fast. Or compromise with a well optimised, lightweight font stack (usually from Typekit), if we’re not using italics we don’t load italics!

    • I agree that the “large screen” test should be changed to a connection speed test. Anyone on a mobile device could be on blazing fast WiFi – why give them different fonts?

      I think Foresight.JS would be a good place to start for this. I’m not sure if you’d consider it “reliable”, but some information is better than nothing.

  9. Mark Szymanski
    Permalink to comment#

    Yea FOUT is something I really try to avoid, even if only initially. Using stuff like Typkit and Google fonts are great and all but I find storing the actual fonts in the site directory and calling them in the stylesheet works great. Sure there’s a bit of page weight it adds but I feel the trade off is worth it , is it really that bad?

    Also, I’ve noticed that not only can there be a FOUT when linking to font’s on other servers but if the fallback font has a different line-height or padding some elements can shift around a bit. Adding to the awkwardness…

    • Ryan Wheale
      Permalink to comment#

      You are wrong – Hosted font files are almost always faster than hosting your own. Most hosted fonts are on a CDN, which is always going to be faster than non-CDN hosting. Also, files hosted at your domain would load sequentially, usually 2 at a time… where as files hosted at another domain load in parallel to the files on your domain. Lastly, a hosted font file (like Open Sans on Google’s CDN) is likely to already be cached in a user’s browser… meaning the file doesn’t even load at all when the user first visits your site. If you decided to host your own Open Sans, then it would have to load for every user who visits your site.

  10. I recently posted a video on how I go about serving up fonts. It doesn’t really cover anything in this article, but deals with subsetting, encoding, etc. You cats might want to give it a look-see.

  11. I find that media queries are the best solution as well.

  12. This all gets better the more information we can get our hands on regarding the clients situation.!

  13. Permalink to comment#

    Thanks for this article… I have been fishing around for ways of dealing with this. Sometimes Google Webfonts will bring my page load to a screeching halt. Looking forward to when we figure this out a standardized way to do this.

  14. Elizabeth
    Permalink to comment#

    See, my question is: how much of a performance hit are custom fonts? On at one of my sites, which was designed mobile-first, the two fonts I’m using don’t seem to slow load — possibly it’s because the thing is otherwise very lightweight — and I can’t figure out how to isolate the fonts as a factor in load time.

    • Permalink to comment#

      If you’re using Chrome you could use the inspector. Right click somewhere on the page and go to “Inspect Element” then click the “Network” tab and reload the page with hard refresh (CTRL+SHIFT+R)

      Should get some idea from the output

  15. That’s useful. For the longest time I’ve been wondering on whether or not the page load time is worth sacrificing just to use a custom font or not because there’s a lot of people out there with a slow internet connection and that’s a really big turn-off for them. For example, if I can’t see any text within the first few seconds – I’ll just leave the page.

  16. Permalink to comment#

    Personally i can’t ignore using custom fonts for better performance, but i think it’s easy to save some page weight by choosing which fonts and how many of them. i usually use Google font api and choose maximum 2 of most popular fonts, ’cause this way the chances are much more that popular fonts have already been downloaded and cached.

  17. Permalink to comment#

    Thanks for clarifying that… Custom fonts are absolute useable in enterprise environments, e.g. for public sites like facebook? rather not… – completely regardless of the delivered performance.

  18. David Warner
    Permalink to comment#

    I was unaware about the AJAX method. This is going to be truly helpful to me. Can you let me know is there a standardized way to do this?

  19. For Typekit we load only if a screensize is detected through media queries. a few weeks ago we created a tutorial for that here (I just translated it to english, sorry if you see any typos!). The method comes from Jeremy Keith and some conditional loading tests. This is another approach, feel free to drop us a line!

  20. Permalink to comment#

    Great notes here. I’d just add one last technique, which got my custom font file size from 900KB down to 17KB.

    Not always the best option, but still pretty interesting. I’ve used Cufón on this website. Cufón is a little Javascript engine, which allows you to load the very specific characters you want. I even had the chance to write a tutorial on that for Inspired Mag. Check it out!

  21. Permalink to comment#

    Would seem that the media query way of doing it is simplest. Problem is you have no way of knowing what device or speed of connection the person has from a width test. Sure there’s a “decent chance” that >1200px is likely to be a desktop but could be anything really.

    I guess it’s up to the site owner to study their analytics and determine more accurately what sort of user demographic they have and then work out if it’s an acceptable decision to use potentially heavy fonts.

  22. Seriously awesome article. I love me some custom fonts, but I hate slowing down my sites. I’ll definitely take some of these techniques into effect!

  23. Whilst fonts are a concern, I still see a vast amount of websites that have (literally) a dozen linked CSS files and maybe the same amount of linked JavaScript files in the head of the document. Quite often none of this stuff is gzipped before being served. I get a lot more twitchy over 10 x 10kb linked files than I do a single 100kb font file.

    My feeling is there’s an awful lot of other things people can do to increase the load time and render time of their documents before they worry about ditching their favourite font. That doesn’t mean we shouldn’t be sensible though – unless you really, really need that font in 3 different weights and italics then don’t include those variations!

  24. Simon
    Permalink to comment#

    A question regarding Google Fonts;

    Are there any differences in load time (or preformance) with using a google font for just one header, compared to all the text on a site?

    Since the actual d/l of font files is what primerely affects load time, I would think using the font for all content wouldn’t make any difference? But I’m guessing..

    /Simon

  25. has anyone seen any benchmarks on rendering speed (not download speed) of different font types, ttf, woff, svg? If not how does one measure it?

  26. Permalink to comment#

    Very interesting, great article. I’ve setup RUM (Real User Monitoring) at PingDom which is a front end user monitoring service. It’s got wayyyyy better user experience tracking that GA (Google Analytics) because it was built specifically to measure what the user goes through. I’ve had a couple hundred views now and I’m seeing some interesting data. It measures:

    Redirect -> DNS -> Connect -> Send -. Receive -> DOM Processing -> Render

    Interestingly, overall my median page load is 1.4 seconds, which I am very happy about. BUT, in my graph I can see the Render time has some HUUGE spikes in it, one of them is 35 seconds long.

    As far as I’m aware this is the only tool I’ve ever used that actually gives me this sort of data so I thought I would share. All you have to do is setup some code similar to analytics, and the code is async’d in and the file is tiny, so no real impact on the site.

    I’m only really scratching the surface though, there’s some super interesting data on mobile and tablet render time too. It’s got browser info, experience index, by country data, by page, and more.

    Anyone else used other tools like it?

  27. When I’m talking to clients, how can I accurately explain how much effect a webfont will have? Am I right that it’s only about 200kb to 400kb of information, so about the same as adding another photo to a big hero slider on the front page of their website? And that if it’s something common like Open Sans, many of their site visitors will already have the font cached? Correct me if I’m wrong.

    • Permalink to comment#

      400kb here and there can really start to add up. That’s why the average webpage now weighs in at well over 1mb including all of its assets. Yes, if you serve Open Sans from the Google CDN then there’s a good chance your visitor will have it cached, but if you choose an unusual font and don’t/can’t use the CDN then there will be a performance hit compared with using a web safe font that the visitor has installed locally.

      Being old school I tend to freak out when any single asset is over 50kb in size :-)

      My thoughts on the matter are:

      1) If you use external fonts, try and use ones on a CDN.

      2) Try and use “standard” fonts, for example Open Sans, Droid Sans, etc. There’s more chance your visitors will have these cached, and they’re proven to render/display reliably.

      3) Try not to use more than 1, maybe 2 custom fonts at the most. I think a site using 3 or more different typefaces is likely to look odd anyway.

      4) If you use icon fonts, run them through a tool such as Icomoon.io whereby you can select only the icons you want and therefore reduce the size of the font substantially.

    • Thanks! I’ve visited a few site recently that used three or four web fonts, plus various weights, plus big sliders and graphics all over, and the site were way too heavy. But I think for my current client, one common web font will do the trick – she wants her website update to look fresh and modern and I think part of that will be choosing a new typeface.

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".