10 ways to speed up web font loading
Fonts are popular tools on the web nowadays. Most modern websites use custom fonts, usually from Google Fonts, because they add a personal touch to the website’s interface. However, fonts, when improperly implemented, hurt loading speeds and performance for the user due to the bandwidth and network request requirements for them. Luckily, you can solve these problems and keep your website fast while maintaining its personality. Here are 10 methods to reach these performance improvements.
How to make web fonts load faster
1. Self host your fonts
When you go on a website and look at the HTML, you often see 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&display=swap"
rel="stylesheet"
/>
That means the website is using Google Fonts to load fonts. Google Fonts is excellent for prototyping, as it is straightforward. Sadly, it is terrible for performance. Performance is bad because Google Fonts has a complicated string of requests to get a font, which adds significant latency.
As you can see, Google Fonts loads fonts in a pretty convoluted way. However, you can reduce the number of requests you need by self-hosting the font and putting the @font-face
declaration inside your CSS bundle instead of an external stylesheet. A tool like Google Webfonts Helper can be helpful for this.
You can also use tools built for specific frameworks like next/font
for Next.js. These tools automatically download the font file and include it in the build process, allowing you to take advantage of the better performance without having to manage the font files yourself.
2. Use modern web font formats
System font formats like TrueType (TTF) or OpenType (OTF) are not designed for the web usage. Both TTF and OTF are uncompressed, which often makes them 3x+ larger than they should be, decreasing load speeds. To solve the problems created by these fonts, a newer font format, WOFF, uses zlib, a compression algorithm similar to what is commonly used in .zip
and .gzip
files, to compress traditional TTF or OTF fonts. Later, Google created WOFF2, which is the similar but even smaller because it uses Google’s Brotli instead of zlib.
These font formats should be used pretty much always for the significant size advantages they have. Additionally, modern web font formats are almost universally supported:
You can get away with just using WOFF2, as it offers the best compression and ~98% of web users support it, or include WOFF as a fallback to reach some older browsers.
3. Subset your fonts
Font subsetting means trimming your fonts down to only the characters you need. Subsetting can yield massive amounts of size savings without drawbacks as long as you are not using the characters you remove. The simplest way to do this is subsetting to remove languages that you do not use. For example, take Inter, one of the most popular fonts. If you include all alphabets, which include Latin, Cyrillic, Vietnamese, and Greek, the size of the WOFF2 font is 95kb. However, chances are you are not using all of those alphabets. Removing all characters outside the English language reduces Inter’s size to just 16kb!
There are many ways to subset fonts, including Google Fonts (and by extension, Google Webfonts Helper), Everything Fonts, and fontTools.
The size reduction benefits performance, but you can do even better if you are willing to take on more complexity. Instead of subsetting by wide character ranges, you can subset to include only the characters you use. Tools like fontTools allow you to subset fonts by arbitrary character lists. The problem with this approach is that you need a complicated build process to get every character you use. Or, of course, you can manually add each character, but that is a lot of work 🙁. Ultimately, you can get most of the benefits with much less work by just removing languages/alphabets you do not need.
4. Use font-display
By default, text will not appear in many browsers until the correct font is loading. That behavior is called Flash of Invisible Text, or FOIT. Some other browsers display text using the fallback font while it is loading, ensuring text is not invisible, but that can cause a layout shift.
Luckily, you can customize font loading through the font-display
option in your @font-face
declaration. The two recommended values for font-display
are swap
and optional
. swap
uses a fallback font and then switches to the custom font once it is loaded, and optional
blocks page load for a maximum of 100ms to let the font load, and if it does not, it uses a fallback font.
@font-face {
font-family: "Example";
font-style: normal;
font-weight: 400;
src:
local("Example"),
local("Example"),
url(https://example.com/example.woff2) format("woff2");
font-display: swap;
}
font-display: optional
is the best for when you don’t need the font to be loaded because it prevents any layout shift and ensures the text is not invisible. However, font-display: swap
is best when you need the font to load because it swaps in the font even if it takes more than 100ms. font-display: swap
can cause issues with layout shifts like mentioned above, but the next tip can help you solve that.
5. Match your fallback font with your custom font
Fonts are usually spaced and sized differently. For example, Merriweather is larger than Georgia, even if the CSS font size is the same. These inconsistencies can cause a layout shift if you use font-display: swap
and make fonts less consistent if you use font-display: optional
.
Luckily, you can configure your fallback font to look much more like the web font you are using. Matching both fonts can be done by customizing spacing and font size through CSS properties in the @font-face
to remove inconsistencies. A helpful tool for this is Font Style Matcher, which allows you to look at two different fonts, configure various spacing properties, and see a demo of the layout shift.
6. Use a CDN
CDNs are great for speeding up static content delivery. They deliver content closer to your users and often offer other ways of speeding up delivery. Hosting your fonts on a CDN with all your other static assets is a good idea. Using a CDN also reduces server costs, as CDNs are generally cheaper than serving the request from your source server.
Most major cloud providers, like AWS, Azure, and GCP, all have CDN services. You can also use a CDN like Cloudflare if you can’t use a CDN integrated with your other hosting tools.
7. Preload your fonts
Preloading is often a good idea for fonts, as it lets the browser know it needs to download a resource sooner and increases that resource’s priority. Instead of waiting to load and parse the CSS containing the font declaration, the browser can start downloading the font immediately.
Unfortunately, preloading comes with a tradeoff: the browser normally detects whether the website uses a font on the page before downloading it, even if the @font-face
is present. If the browser finds no text with that font, it will not download it. However, the browser cannot do this with preloaded fonts because the browser must start downloading the font immediately.
Now, you might know that you always use the fonts you include with @font-face
, and therefore there is no chance of an unnecessary font load. Unfortunately, there is one other potential problem. If your font is not immediately needed, the drawbacks of deprioritizing the loading of other resources might outweigh the benefits. However, if these two potential issues aren’t problems for you, preloading can greatly speed up your fonts.
8. Use local()
Depending on the font, users can often have the font you are using locally installed on their machine. If they do, you can use the font locally to prevent any performance degradation from downloading a custom font through a local()
statement in your @font-face
rule.
@font-face {
font-family: "Awesome Font";
font-style: normal;
font-weight: 400;
src:
local("Awesome Font"),
url("example.com/awesome-font.woff2") format("woff2");
}
This @font-face
checks if the user has the font locally, and if they do not, downloads it remotely. That means that users who already have the font don’t need to redownload it. If you want to focus on fonts that computers usually have, you can check out Windows 11’s font list and macOS Sonoma’s font list.
Unfortunately, it is essential to note modern browsers limit locals()
capability to prevent fingerprinting. Webkit only allows local
to load fonts installed by default in the operating system, meaning user-installed fonts will not appear.
9. Implement Caching
Caching is very important, especially if you have lots of repeat visitors. Caching allows the font to load from the disk after the first time it is downloaded. You can implement caching through the Cache-Control
header. If you use a CDN, it is simple to do from the dashboard. Otherwise, you can do it by simply sending a header with your font responses.
Cache-Control: max-age=604800 // 1 week
The method of doing this depends on your server implementation.
10. Don’t use custom fonts
I bet you didn’t see that one coming 😉. While all of these techniques are great, ultimately, the best performing web font is no web font. System fonts are great for unbranded text like body text. Even beyond the performance advantages, properly implemented system fonts look far more well integrated because they use the same font as the parent operating system. The feeling of integration has led companies like GitHub to use a standard system font stack.
You can implement system UI fonts through a system font stack like this one, which this blog uses:
font-family:
-apple-system,
BlinkMacSystemFont,
avenir next,
avenir,
segoe ui,
helvetica neue,
helvetica,
Ubuntu,
roboto,
noto,
arial,
sans-serif;
The font stack above contains a variety of fonts, first listing fonts for popular operating systems, then listing web safe fonts. You could also just use one font family, system-ui
. However, system-ui
is known to have some internationalization issues when users have default languages that are not the webpage’s language.
Conclusion
That is all! I hope you enjoyed learning how to optimize your web fonts. Either way, you should now be able to speed up your website significantly. If you want to further improve the speed of other areas of your website, like images or JavaScript, check out these articles:
If you enjoyed reading this, sign up for the mailing list below and subscribe to RSS. Thanks for reading!