Professor Sloth

Free web performance master class

Learn about web performance and how to make your site faster, delivered straight to your inbox.

5 Tips To Make Google Fonts Faster

5 Tips To Make Google Fonts Faster

Google Fonts is the defacto way many developers add custom fonts to the web. But it is often one of the slowest resources on your website. It’s frustrating and ironic that Google’s own font service is problem in many web performance audits–but it doesn’t have to be! Here’s 5 ways to turbocharge your fonts with Google Fonts to make it download less, load faster, and reduce layout shifts on your website.

Tip 1. Avoid @import statements

There are two ways to install Google Fonts from their website today: “<link>” and “@import”. They look something like this:


<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
HTML Links

<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');
</style>
CSS Import Statement

The @import approach lets you keep fonts with the rest of your stylesheets, so I understand why you’d want to use it. Unfortunately, by placing an @import in your CSS file, you force the browser to download and parse that file before the fonts can even start loading. It introduces unnecessary wait time.

The first thing to try is to switch to the <link> style installation.

Tip 2. Use fewer fonts and variations

Our performance rule of “do fewer things” applies. If you use fewer fonts, then obviously they will load faster, duh! Most websites should be able to use one or two fonts: a base font and a header or accent font.

Try to keep your design as simple as possible. If you think you need 3 or more fonts, consider whether that is worth a site that loads in 4 seconds instead of 2.

Load Fonts When You Need Them

You don’t always need fonts on every page of your website. For example, we use a base font and a header font on most of our pages, and then a separate “content font” on long-form text like this. Every page will load our base and header font, but only content pages load the content font. That saves about 30 kB and 50 ms from our base load time on most pages.

We do this in Jekyll by having 2 Google Font tags and conditionally loading the content fonts with a frontmatter variable.


---
layout: web-performance-post
title: "5 Ways To Make Google Fonts Faster"
content_fonts: true
---
Post frontmatter that uses content fonts

<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@700&Muli:wght@400;700&display=swap" rel="stylesheet">
{% if page.content_fonts %}
<link href="https://fonts.googleapis.com/css2?family=Lora:wght@400;400i;700&display=swap" rel="stylesheet">
{% endif %}
Global head that conditionally loads content fonts

There should be similar ways to do this for Apollo, Ghost, WordPress, Next, or whatever other platform your website is based on.

Limit Font Weights

Even if you are only using a few fonts, they could be very large and slow if you are downloading every possible variation and weight of the font. For example, if your site uses the popular Roboto font, it takes an additional 30 ms and 11 kB for each font variation you use. If you blindly select all of them, this can add up quick.

Network Cost of loading all Roboto Font Weights
Network Cost of loading all Roboto Font Weights

Each weight is further doubled if you also need it in italics.

Tip 3. Specify the characters your need

Typically, Google Font’s doesn’t know what you are going to show in your fancy font. So it has to send everything. Literally every character in every alphabet, just in case you want to use it. What a waste of bytes!

For most sites, we only need the font for characters in one alphabet. And sometimes, we’re only need to show a few headline words. The Google Fonts CSS2 API supports a text parameter where we can provide the list of characters we intend to use, and it will shrink down the response for us.

For example, an entire weight of the Roboto font is about 11 kB. But if we restrict to to just the basic Latin alphabet, numbers, and common punctuation, it’s cut almost in half to 6 kB.


<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400&display=swap
&text=1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz%20%21%22%23%24%25%26%27"
rel="stylesheet">
Limiting the Roboto Font to base characters

If you are only using a font for a headline hero message, you can get even smaller! Setting text=5 Ways To Make Google Fonts Faster results in only a 2 kB font!

Tip 4. Bypass the Google Font loader

Google Fonts works as a 2-step request process. The first request is the <link> tag to https://fonts.googleapis.com/css2 that you include on your page with your desired fonts. This is the font loader, a CSS file with all the font definitions you asked for. Once this request is complete, a second series of requests is made for each font used.

That’s two, serial, and blocking requests that can slow down the rendering of your content.

You can speed this up by including the CSS font definitions directly in your own CSS. Here’s how:

  1. Place the <link> tag on your page for your Google Fonts, specifying the fonts, weights, and text that you need.

  2. Open up Chrome DevTools and look at the results of that css request. It will be a CSS file that looks something like this:


@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('https://fonts.gstatic.com/l/font?kit=KFOmCnqEu92Fr1Me4GZNCzcPbOHTt6tqXl2TMWgtUADtbNE0FwjR60ub0BtuliV9nzY5opeRF6O-FnZsaJLetvV-9mXgaxv7xBV8jmt2chWZ7OuZw6siU4A&skey=a0a0114a1dcab3ac&v=v30') format('woff2');
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('https://fonts.gstatic.com/l/font?kit=KFOlCnqEu92Fr1MmWUlvBh0_IsHA06hvWViQJH84UwXqadI5GH6rkU6c1RhjmSh-mjE8oYqOCqC7EXNvZZ3Tj85H82LlaBb0yRZ5iW51bwqE7-6exqgvXI1IEVo&skey=c06e7213f788649e&v=v30') format('woff2');
}
Google's Font Loader Response
  1. Copy the text into your site’s CSS. We use SASS and have a _fonts.scss file that we include just for this purpose. Note: If you did not limit the text characters in your font request, you’ll see a lot of @font-face definitions. You only need to copy the character sets you’ll need. For us, that’s just the Latin characters.

  2. Remove the Google Fonts <link> tag from step 1. You’re now referencing the font files directly from your CSS and skipping the loading request entirely.

Text Visibility During Font Load

Make sure to keep the font-display property! This directive tells the browser whether to show or hide your text while waiting for fonts to load. If you show text too early, it can cause a nasty layout shift when the fonts are all replaced.

Checking for Local Fonts

You may be using a font that the end user already has installed on their computer. Wouldn’t it be great if you could just use that local font and skip the request entirely? Well you can!

The src directive allows you to specify multiple values, which allows us to make an attempt to reference a local font before hitting the URL. In this example, I added an attempt to grab local('Roboto') before downloading it from Google.


@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: local('Roboto'), url('https://fonts.gstatic.com/l/font?kit=KFOmCnqEu92Fr1Me4GZNCzcPbOHTt6tqXl2TMWgtUADtbNE0FwjR60ub0BtuliV9nzY5opeRF6O-FnZsaJLetvV-9mXgaxv7xBV8jmt2chWZ7OuZw6siU4A&skey=a0a0114a1dcab3ac&v=v30') format('woff2');
}
Font Directive with local attempt

Tip 5. Host Your Own Fonts

If you’ve got yourself a fast CDN, it could be faster to host the fonts yourself rather than depending on setting up a connection to Google. Not that Google’s services are slow, but it is another connection, another DNS lookup, and another SSL handshake that needs to happen to load your page.

If your website host is already fast, hosting the font files directly can further speed things up by skipping all the connection setup steps to Google Fonts. Simply download the font files from the URLs and save them into your website. Then, update the URLs to match your local paths.


@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: local('Roboto'), url('https://yoursite.com/fonts/roboto-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: local('Roboto'), url('https://yoursite.com/fonts/roboto-700.woff2') format('woff2');
}
Font Directives from your website host

Preload your fonts

You can speed this up further if you add preload directives to the <head> of your website that instructs the browser to fetch the fonts before the CSS has completed:


<link rel="preload" href="https://yoursite.com/fonts/roboto-400.woff2" as="font" type="font/woff2">
<link rel="preload" href="https://yoursite.com/fonts/roboto-700.woff2" as="font" type="font/woff2">
Preloading the Roboto Fonts from your host

Note: If your web host is not fast, and does not support HTTP/2, this might end up slowing things down. In older versions of HTTP, each request required its own setup, and your server is probably not as fast as Google’s.

Just How Fast Is It?

We made these changes to RequestMetrics.com a few weeks ago and the performance benefits were real and significant. Firstly, check out this Lighthouse Score.

Google Lighthouse scores from self-hosting Google Fonts
Google Lighthouse scores from self-hosting Google Fonts

That’s cool and all, but as we’ve talked about before, Lighthouse can lie to you. We’re a real user performance monitoring company. What’s the real user benefit?

Google Font Improvements to Real Page Loads
Google Font Improvements to Real Page Loads

Applying these changes to fonts dropped our Median user load time from 2.2 seconds to 1.9 seconds. The 95th percentile fell from 8 seconds to 5 seconds.

Google Font Improvements to Real First-Contentful Paint
Google Font Improvements to Real First-Contentful Paint

We see these same improvements in our Core Web Vital metrics, with significant drops to our First Contentful Paint score.


With some consideration to your font choices and simple tweaks to how you install Google Fonts into your website, you can greatly improve the load performance for your users. Don’t take our word for it though, check out your real user performance data with Request Metrics and see how much faster it gets.

Todd H. Gardner
CEO Request Metrics

Todd is a software engineer, business leader, and developer advocate with 20+ years of experience. He is a co-founder and CEO of TrackJS and Request Metrics, and previously a independent consultant who helped build products at Thomson Reuters, Reach Local, and LeadPages.