Ever since I first learned about variable fonts, I’ve wanted to use them in my own work. After learning that Source Serif and Inter both had variable versions, I started switching this site over to use them. Here’s how I implemented the change, and what I learned along the way.

What are variable fonts?

Variable fonts are a new type of font file. Instead of requiring individual files for bold and light weights, or regular or italic variations, you only need a single variable file.

A responsive lettering example, courtesy of Erik van Blokland.

Why use variable fonts? In addition to technical simplicity (1 font file instead of multiple), variable fonts tend to come in smaller files than their more traditional cousins. Smaller files mean faster load times. Faster load times mean a better internet.

How I implemented variable fonts

I started with Clearleft’s case study of implementing variable fonts. The instructions they provide are incredibly detailed and useful, so I won’t try to re-create them here.

Before I switched to variable fonts, I was loading Source Serif in Roman and Italic at a two different weights. I used typekit’s CSS-only loader, as it was super-speedy compared to the javascript equivalent. To get those two fonts from Typekit’s server took 4 requests, bringing the page to a total of 8 requests .

First Byte Start Render Requests Bytes in Speed Index Typekit fonts 0.21s 0.80s 8 80 KB 0.82s

My initial attempt at including a variable version of Source Serif, along with introducing Inter, resulted in a surprisingly substantial increase in most metrics.

First Byte Start Render Requests Bytes in Speed Index Typekit 0.21s 0.80s 8 80 KB 0.82s Variable 0.22s (-0.1) 0.70s (-2) 6 (+464) 544 KB (+0.19) 1.12s

Looking into this, I realized that the variable font files were huge: Inter weighs in at 387kb, making up most of the difference. What happened? I thought variable fonts were supposed to be small?

It turns out that the variable font files I was using include a massive amount of characters: Diacritics for many languages, Cyrillic characters, Greek characters, and so on. I didn’t need most of those; I write in english, and system fonts can support automatic translations.

So I used a tool called glyphhanger to subset my fonts to just latin characters, removing most of the characters I wouldn’t need. In the case of Inter, this resulted in a 300kb reduction — that’s a 78% reduction.

With the new subset fonts, my numbers were looking much better:

First Byte Start Render Requests Bytes In Speed Index Typekit 0.21s 0.80s 8 80 KB 0.82s Variable (subset) 0.21s (-0.2) 0.60s (-2) 6 (+82) 162 KB (-0.17) 0.65s

Fanstastic! The upsides were great:

1 new font , Inter (previously I was relying on system fonts for sans serif)

, Inter (previously I was relying on system fonts for sans serif) Access to the full spectrum of font weights (previously I only had regular and bold)

(previously I only had regular and bold) A Speed Index improvement of 21%

And there was only one downside:

The site downloads an extra 82kb on initial load :(

But wait! Because I am serving the fonts myself, I have better control over caching. Before I made this update, I was relying on Typekit’s caching instructions, which only kept the css for a maximum of 10 minutes. Now, 100% of my static assets are cached for more than a week. This means return visitors will experience better performance.

What I learned

Wrapping it all up:

Variable font support is approaching critical levels for wide adoption Almost all modern browsers support variable fonts, accounting for 79% of internet users. There are high-quality variable fonts that you can download and use today Nick Sherman has created a variable font repository if you’d like to browse and try what’s available. Variable fonts can improve performance if you subset carefully - While it’s not 100% out-of-the-box, there ar easy-to-use subsetting tools like glyphanger and fonttools that can help you over the finish line.

Next time you’re booting up a project, give variable fonts a try.

A note on fallback fonts

Astute readers will note that I chose not to implement fallback fonts for older browsers. The reason for this is twofold: first, I’m lazy. I wanted to ship this update without getting in the weeds. Second, I don’t care if my site doesn’t look identical in all browsers ever. I am confident that it’ll look good in whatever fonts match my detailed system font stacks.

When I originall published this post, I was experiencing a weird bug: in Safari, all instances of Inter were rendering in italic. No matter what I did, I couldn’t force Safari to use the normal (upright) version of Inter. I reached out for help:

For some strange reason, Inter shows up in italic on Safari, despite specifying `font-style: normal` in the font-face declaration. Any ideas why? @rsms (2/2) — Matthew Ström (@ilikescience) March 3, 2019

My question was almost immediately answered by the creator of Inter, Rasmus Andersson:

This is a known bug in Safari with variable fonts. You either need to use the single-axis variable fonts with Safari, or explicitly set the “slnt” axis position to 0 for :root and 1 for em, i, etc. — Rasmus Andersson (@rsms) March 3, 2019

Unless you need the intermediate italic grades, I’d recommend using the single-axis version of Inter. Should speed up your page loads in common cases as well (ie when no text is italic.) — Rasmus Andersson (@rsms) March 3, 2019

And that’s exactly what I did: I replaced the single Inter font file with two files: one for the italic variant and one for the normal variant. As predicted, this fixed the bug. Hooray! Here’s the performance breakdown on a page that uses the same fonts as before (ie no italic sans-serif):

First Byte Start Render Requests Bytes In Speed Index Typekit 0.21s 0.80s 8 80 KB 0.82s Variable (subset) 0.21s (-0.2) 0.60s (-2) 6 (+82) 162 KB (-0.17) 0.65s Variable (single-axis) 0.20s (-0.2) 0.60s (-2) 6 (+97) 179 KB (-0.22) 0.60s

I’m loading even more data than with the single-axis font (why? I honestly have no idea), but see a net decrease in speed index due to faster rendering. I’ll be exploring this in more detail in the future, but for now, it’s a great start.