Blog: Web Design
Speed lines from moving train

Load Google Fonts Asynchronously For Page Speed

Avatar for John Locke

John Locke is a SEO consultant from Sacramento, CA. He helps manufacturing businesses rank higher through his web agency, Lockedown Design & SEO.

Web developers who are mindful of user experience, performance, and SEO pay attention to page speed.

If you’ve ever tested your website on Google Page Speed Insights, you may have seen a message like this:

Eliminate render-blocking JavaScript and CSS in above-the-fold content.

If you are loading Google Fonts via a normal style sheet link in the <head>, then there’s no doubt that link is being looked at a render-blocking file.

Any file that the browser needs to render the page, where it will not show the page without it, is known as part of the critical path. Normally, any CSS file is part of this critical rendering path.

Though Page Speed Insights is a good tool, remember that Google still uses what real users see as a metric for judging page speed and user experience.

So what we want to do is improve our page speed for real users first, but also reduce the number of files on that critical rendering path.

When I really starting digging into this problem, one of the first solutions I found was the Web Font Loader — a joint project between Google and Adobe Typekit. Any browser that supports @font-face can use this.

Why Use The Web Font Loader?

On good broadband networks, deferring the loading of fonts will only save a little bit of time. But on mobile devices — especially 3G devices, it will deliver much faster page rendering. Better page speed on mobile devices means over half of your potential audience will stick around on your website, and not bounce out. (Note: bounce rate is when people leave your site immediately after viewing a single page.) This leads to more conversions, more signups, and more sales.

The Web Font Loader uses a little sleight-of-hand to make site visitors feel like the page is rendering faster.

CSS blocks the rendering of the page, which gives impression of slower page speed. What the Web Font Loader does is defer the loading of Google Fonts until after other parts of the page have started to render.

Advantages of Web Font Loader:

You can use it with Google Fonts, but also Typekit, Fontdeck, or Fonts.com.

This script loads fonts after the critical path, including any CSS in the element.

Disadvantages:

This method uses JavaScript, so anyone with JavaScript disabled on their browser will be served the fallback font-families instead.

How To Use the Web Font Loader

In your page, include a link to the Web Font Loader script. You can set this link to load the latest version, but for performance, it is better if you link to a specific version of the script.

Then, indicate what font families you would like to load from which font service.This is what the code looks like on this very site (We’re using Google Fonts.)


<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js"></script>
<script>
 WebFont.load({
    google: {
      families: ['Source Sans Pro:400,600,700,400italic,700italic', 'Roboto Condensed:400,700']
    }
  });
</script>

There are different methods for Typekit, Fontdeck, and Fonts.com. You can consult the documentation on Git Hub for the Web Font Loader project for specific instructions.

Another way you can use the Web Font Loader is in the of your pages. This method uses JavaScript to load fonts ansynchronously. Google will show you this method when you go to use Google Fonts if you click on the JavaScript tab.

JavaScript Google Fonts Asynchronous Code

This is what this script looks like. (It is similar to the previous script, but utilized a different way.)


<script type="text/javascript">
  WebFontConfig = {
    google: { families: [ 'Roboto+Condensed:400,700:latin', 'Source+Sans+Pro:400,600,400italic,700italic,700:latin' ] }
  };
  (function() {
    var wf = document.createElement('script');
    wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
      '://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js';
    wf.type = 'text/javascript';
    wf.async = 'true';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(wf, s);
  })(); </script>

In my own testing, this method seemed a little slower than what I am using, putting the former script in the footer. Either way is a compromise. You must test for yourself and decide what works for your site.

The Web Font Loader defers the loading of Google Fonts until after the page starts rendering. But this is only a partial solution.

Webkit Browsers and the FOIC

Webkit browsers like iOS and Safari, will render a flash of invisible content (FOIC) while they wait for the font to load. Firefox renders the fallback font while the specialty font loads. This article by the Filament Group seemed to point towards using @font-face and data URIs to prevent this.

But about a month later, they came up with a better solution, that serves up a fallback font while waiting for the Google Fonts to load asynchronously.

This solution uses a script called Font-Face Observer to “listen” for the font to loaded, at which point, it can add a CSS class to the document, or output a message to the console log.

Font-Face Observer will also load fonts that have a @font-face declaration in the main CSS. More on that in a second.

How you get around the flash of invisible content on Safari and iOS? The Filament Group figured out they could set a style rule for the site for the fallback font-family to start with. When the specialty font finishes loading, this script can set a class of fonts-loaded directly to the <html> element. Then, a second font-family rule that applies to the fully loaded page would take over.

Here’s what everything looks like for a website loading Sans Source Pro as a specialty font:


/* CSS */
/* You should be able to use @import or Google Fonts link as well,
 * these also generate a @font-face rule.
 *
 */

@font-face {
    font-family: 'source_sans_proregular';
    src: url('http://www.yourwebsite.com/path-to/fonts/sourcesanspro-regular-webfont.eot');
    src: url('http://www.yourwebsite.com/path-to/fonts/sourcesanspro-regular-webfont.eot?#iefix') format('embedded-opentype'),
         url('http://www.yourwebsite.com/path-to/fonts/sourcesanspro-regular-webfont.woff2') format('woff2'),
         url('http://www.yourwebsite.com/path-to/fonts/sourcesanspro-regular-webfont.woff') format('woff'),
         url('http://www.yourwebsite.com/path-to/fonts/sourcesanspro-regular-webfont.ttf') format('truetype'),
         url('http://www.yourwebsite.com/path-to/fonts/sourcesanspro-regular-webfont.svg#source_sans_proregular') format('svg');
    font-weight: normal;
    font-style: normal;
}
body {
  font-family: Helvetica, Arial, sans-serif;
}
.fonts-loaded body {
  font-family: 'Source Sans Pro', sans-serif;
}


/* JavaScript */
/**
  * I put mine in the footer. You can experiment with where this goes.
  *
  */
<script src="http://www.yourwebsite.com/path-to-file/js/fontfaceobserver.js"></script>
<script>
(function( w ){
    // if the class is already set, we're good.
    if( w.document.documentElement.className.indexOf( "fonts-loaded" ) > -1 ){
        return;
    }
    var fontA = new w.FontFaceObserver( "Source Sans Pro", {
        weight: 400
    });
    var fontB = new w.FontFaceObserver( "Source Sans Pro", {
        weight: 700
    });
    w.Promise
        .all([fontA.load(), fontB.load()])
        .then(function(){
            w.document.documentElement.className += " fonts-loaded";
        });
}( this ));
</script>

This gives page visitors the content, with a fallback font, without waiting for the Google Fonts to load, which blocks page rendering — making page rendering faster.

This also prevents Webkit browsers from having invisible content while waiting for the specialty fonts to load.

This setup probably isn’t ideal for every site. But for stripped down sites with only a couple of fonts, it can improve page speed.

Now what Filament Group did to cache the loaded fonts in a vistor’s browser was add a cookie via server-side includes that looked like this:


<!--#if expr="$HTTP_COOKIE=/fonts\-loaded\=true/" -->
<html lang="en" class="fonts-loaded">
<!--#else -->
<html lang="en">
<!--#endif -->

Now, they are running Perl server-side include scripts on flat HTML files. Unless you have a similar setup, that will be of little help to you.

I’m pretty sure there is a way to do this in PHP for WordPress using $_COOKIE and set_cookie(). I’ll come back to this as I test further.

Avatar for John Locke

John Locke is a SEO consultant from Sacramento, CA. He helps manufacturing businesses rank higher through his web agency, Lockedown Design & SEO.

50 comments on “Load Google Fonts Asynchronously For Page Speed

  1. Sounds good John!
    Unfortunately I am not technical enough to pull this off on my website.
    Tried but didn´t do anything.
    I did something wrong… a shame!

    Greetings from Holland.

    Robbert

    1. Ahh, this one is a little tricky, Robbert. This post is more for developers, but it came after much trial and error on my own.

      You should test experiments like this on a staging server (a clone of your site not in the public view). That way, no damage is done to your live site.

  2. Working on a website and wanted to try out Font-Face observer. Not a dev and was having trouble with the javascript needed to make it work. I just wanted to say your example worked perfectly!

  3. Since the loading of the font is differed, is there any FOUC using this method? Also, could we download the JS and roll it into our site’s own JS to avoid an additional HTTP request?

  4. Hi Jonathan:

    There is a little Flash of Unstyled Content. The way around this might be to set a cookie that looks to see if someone has visited before, then add the class name to the body tag.

    For the second question, you can absolutely roll this into your site JavaScript to sidestep the extra HTTP request.

    1. Thanks John! I’ve since implemented this on a test page and I’ve now got a very high score on Google PageSpeed Insights 🙂 Thank you!

      I do still see a FOUT however, which irks me a little. I even set the cookie. I’ve been reading around and apparently, Flash of Unstyled Text is preferred over invisible text on page load nowadays.

      Is this what you prefer also?

  5. Hi Jonathan:

    Awesome to hear that you’ve improved your Google PageSpeed score. The cookie is where I hit a roadblock.

    To answer your other question, if I have a choice between Flash of Unstyled Text and a delay in page rendering, I’ll take the FOUT every day of the week.

    The reason is that I’m willing to trade an instant of unstyled text if it means a half second bump in page load time. Better for users, and Google likes it.

    Ultimately the goal is to attract more people to a page and keep them there until they read the whole page. 🙂

  6. Hi John, thanks for the info above, looks like a great solution.

    In the CSS box above you mentioned that one should be able to use @import or Google Fonts link as well and I was wondering how would I go about that, following the steps you did.

    Thanks a lot!

  7. Hi Serge:

    It is probably better to pass in the font you want to load as shown in the very first code snippet. I have found this method to be more stable. If you want to download each type of font (WOFF, TTF, EOT, etc.) and load them from your own server, you can do that and follow the instructions shown in the third code snippet.

    Thanks,
    John

  8. Thanks for this.

    It’ll kinda ruin the whole site if a user doesn’t enable javascript but it’s really just the smaller scale of users I suppose. I have about 6 URLs that need addressing to this will help the score rise.

    Cheers!

  9. Hi Daniel:

    You’re correct, this solution relies on JavaScript being enabled, so it would be best to have a fallback font-family.

    As always, it is up to the developer to decide whether this is the best approach for their project and their users.

    Thanks for reading and leaving your feedback! 🙂

  10. Very nice tips John!
    I’m a UX designer but I do love front-end. After having my personal blog on WordPress, we tried launching our new community website using the Divi theme. But the problem is that every time the PageSpeed says “reduce additional HTTP requests, etc.” — where I found my Open Sans fonts via Google. I think I should try the JavaScript version as I heard the @import step also blocks the page load, isn’t it? I read this on WPBeginner site where they mentioned this @import method is the old style, and in modern usage one should avoid these. Anyway, thank you so much for such a compilation. Thanks.

  11. Hi Abinash:

    IF you are trying to maximize your site for page speed, and you are using Divi, you are already in a bad position to start with. Divi uses shortcodes to render each part of the page, and the server has to process each one of those shortcodes before the page appears.

    IF you are using WordPress, it will never be as fast as flat HTML files using the same hosting environment. You are almost always going to have blocking files if you are loading jquery in the <head>. This is going to be problematic if your goal is to get a score of 100 on Google Page Speed Insights (which I don’t believe it should be).

    The two things that Google pays close attention to when it comes to page speed are “what is the time to first byte?” and “How long does it take for the initial above the fold content to load?”

    You can find time to first byte by using Chrome Developer Tools > Network and clicking on the first resource that loads (in this case, gsiuxd.co). Getting above the fold content to load fast can be achieved partially by inlining styles for the critical CSS that renders above the fold, getting a fast hosting environment, and reducing HTTP requests and large images.

    Your other question was in regards to using @import, and does that block rendering. In older style sheets, you would load @font-face at the top of the style sheet to grab your fonts from the server. You are correct when you say this is also a HTTP request.

    However, in this method for loading external fonts asynchronously, we are using a fallback font for the default styles, then, once the page has loaded, it adds the class fonts-loaded to the <body> tag and pulls in the fonts via an @import tag.

    I used this particular setup on this very site from summer of 2015 to summer of 2016, but went away from it because the gains were very negligible, and the flash of unstyled content (FOUC) that some users would experience was jarring for some people.

    I invite you to try implementing the Web Font Loader script for yourself and see if it gives you the gains in speed that you desire. It may be the right solution for you, or it may not. Try it to find out.

    Thanks,
    John

  12. It is the most difficult portion to get better Page Speed Insights. Without Google Fonts, the theme will not look beautiful. I tried everything, then I just served the .js file from my website without serving from the Google server and now the problem is gone. It works.

  13. Hi Vsync:

    You could inline the fonts in the critical path. But then the browser has to wait to download those in order to render the page.

    By using asynchronous font loading, the page renders first using the fallback font, then loads the preferred font and switches to using those styles.

    I’ve gone back and forth on using asynchronous font loading on this site (I’m not using it currently). It is something you might consider if you are running a site that is 1) already extremely optimized for speed, and 2) handling a lot of traffic or potential transactions.

    In these instances, the speed boost is worth the extra effort. 🙂

    1. I’ve just tried it, and i’m having a hard time with the result, since the default font (any system font) looks so different than the one i’m lazy-loading, the “jumping” in the style after 2 seconds the font has been loaded seems quite odd, and maybe it might look like a bug to non-tech users.

      I’m wondering if the worst visual experience of font-switching is worth the loading time saved..

  14. Right. the Flash of Unstyled Content (FOUC) is one reason why you might shy away from using this.

    Depending on how large the webfont set is that you’re loading, the larger the gap may be. Still, I have seen many heavily trafficked sites use this.

    In the end, it is a personal decision you will have to make.

  15. I found this also to be a bit jarring – especially because 5 years ago we were all hiding the page until fonts had loaded and then displaying the page with JS. FOUC was a thing to be feared! Now, it seems we are embracing FOUC in favor of performance. One way around this (for text) is to just use system fonts in your font stack 😉

  16. Hi Jonathan:

    You bring up a great point. Best practices for front end development and user experience are constantly changing. I have noticed in the second half of this year that more people are returning to system fonts.

    When you are collaborating in an environment where you have input on design decisions, this is an important conversation to have. Loading external fonts in general will add page weight. This is part of the reason large scale websites have a performance budget of how much they wish to load and at what point in page rendering.

    I appreciate your input. Web design is circular. It all comes around again. Have a great holiday.

  17. Hi Aakansha:

    It also shows how to load Webfont kits from your own server using @font-face. The principle is the same. The fonts load separately from the rest of the document, so they are not render blocking.

    Look about halfway through the article to see the @font-face declaration.

    Thanks,
    John

  18. Thanks for the valuable info.

    I used the first method, but didn’t see any improvement. Pagespeed test shows webfont.js additionally as a ‘render-blocking JavaScript’ and ‘Optimize CSS delivery’ section still includes link to fonts.googleapis.com, just a bit changed.

    Is it the way it should be?

  19. Hi AK:

    When I was using this before, I didn’t use the Google Fonts link, but rather downloaded the fonts and delivered them from my own server.

    One other thing that I experimented with was adding the script for loading the fonts in the footer instead of the header.

    If you are loading the script in the header, or delivering fonts from a third-party, like Google Fonts, that may be why you are still getting the render-blocking warning.

    Note: I am not currently using the asynchronous font loading, as I determined the Flash of Unstyled Content was not worth the incremental speed gains.

    use your own judgement when weighing user experience and page speed. Remember that Google looks at the actual time it takes to load the page (specifically above the fold) and not necessarily the Page Speed Insights score.

    If you are implementing page speed for SEO purposes, Time To First Byte is the critical factor that moves the needle.

    Thanks,
    John

  20. Great ! I was looking for this type of solution for my client. Even though I still don’t get it why Google keeps recommending using this solution and after the page speed test says it’s not good.

    Anyway, great article and thanks.

  21. Hi Will:

    If you are hosting the fonts yourself, and loading ansynchronously from your own server, that should not be a render blocking resource.

    If you are loading from the Google Fonts servers, you are deferring the loading, but because it is a resource hosted on an external domain, that is likely why you are still getting a render blocking warning.

    Remember that Page Speed Insights are suggestions. Google looks at how long your page actually takes to load, not the score on GPSI, although those two figures may be in close correlation.

    Thanks,
    John

  22. This method is very detailed for non-developers like me. I have found another solution for this problem in a shape of a plugin. Simply install Google Webfont Optimizer plugin which is very light weight > activate and you are done instead of wasting a lot of time on customizations.

  23. I tried the above method to load Google fonts asynchronously in two servers. Both the servers are with same configuration but I found that one works and other not. Is there any connection with server configuration? I really need this to increase Google PageSpeed for my sites.

  24. Hi Dilip:

    It sounds like the server configuration isn’t the issue. If you got it to work on one server, and they have an identical configuration, it must be something else.

    You might check the file paths to your font files, make sure that everything looks correct there. Also check the URL for the Font Face Observer JS.

    Thanks,
    John

  25. Thanks for sharing all this work John.

    Just a heads up to anyone else getting the “fontA.check is not a function” error or similar in browser console, using a recent release of fontfaceobserver.js.

    You have to change “.check” in the last snippet in this article, to “.load” as “.check” apparently got deprecated. See Bramstein’s comment dated 1 Oct 2016 here: https://github.com/bramstein/fontfaceobserver/issues/77

    (I am not a trained dev; sorry if I used incorrect terminology.)

    It works for me now. Thanks John!

  26. Tried both ways and they both failed.

    Your way reduced the number of requests and speed, but didn’t seem to load the correct fonts.

    Google’s way was even worse.

    While it did load the correct fonts it added 10 more requests and nearly doubled my load time.

    I’ll stick to what I have.

    1. Hi Mark:

      Sorry to hear this tutorial didn’t give you what you were looking for. On the previous version of this site, I ran this implementation. (Right now, I’m running Typekit). Hope you find what you’re after when it comes to shaving milliseconds off the load time.

Join the Conversation

Your email address will be kept private. Required fields marked *.