Variable fonts: Is the performance trade-off worth it?
Tags: css, webperf, tutorial
Published: 2020-03-23 14:34:16

---
title: Variable fonts: Is the performance trade-off worth it?
published: true
date: 2020-03-05 14:00:17 UTC
tags: css,webperf,tutorial
canonical_url: https://blog.logrocket.com/variable-fonts-is-the-performance-trade-off-worth-it/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/62uo17gzxqvygouhnzv7.png
---
**Written by [Anna Monus](https://blog.logrocket.com/author/annamonus/)**✏️

Variable fonts are popular for two reasons: they expand design possibilities and improve website performance. While the former statement is definitely true since variable fonts do provide infinite typographical choices, the latter only holds under certain conditions.

In this tutorial, we’ll conduct a performance test on a live server to better understand the performance trade-off of variable fonts.

## What are variable fonts?

Variable fonts, as defined by a new [OpenType font specification](https://docs.microsoft.com/en-us/typography/opentype/spec/otvaroverview), don’t come with preset font styles such as bold, italic, or thin. Instead, they consist of one or more design axes that allow us to generate unique values for attributes such as width, weight, slant, and many others.

The design axes are always chosen by the creator of the font, and they differ from variable font to variable font. However, there are five registered axes that are standardized by the OpenType Font Variation specification: weight (`wght`), width (`wdth`), italic (`ital`), slant (`slnt`), and optical size (`opsz`). Besides these, font creators can register any custom axis that users can access with the `font-variation-settings` CSS property.

To learn more about variable fonts, check out MDN’s excellent [v](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide)[ariable fonts guide](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide) or experiment with them on the [V-Fonts](https://v-fonts.com/) or [Axis Praxis](https://www.axis-praxis.org/specimens/ __DEFAULT__ ) test sites.

## How variable fonts impact performance

Before we proceed with our performance test, let’s examine how variable fonts impact website performance.

In general, variable fonts improve performance because you only have to use one font file. Static fonts require a different file for each variation you want to use on the site, while variable fonts are dynamic in nature. In other words, they include all possibilities in a single file, which means only one HTTP request instead of multiple. In addition, you only have to use one `@font-face` rule, which results in a smaller CSS file.

On the other hand, a variable font file is huge, precisely because it contains all the variations. The Roboto Variable Font, for instance, is 3.36MB in TTF format, while a static Roboto font variant is around 165–175KB in TTF format. Even if we need to use all 12 variants, that’s still only around 2MB in total.

Ultimately, the performance trade-off of variable fonts depends on how these two metrics — the number of HTTP requests and the total size of font files — balance each other out.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## The challenge of testing variable fonts

Testing variable fonts can be difficult because most variable fonts don’t have a static version, and vice versa. A typeface is typically either a static or a variable font, but not both. In fact, I could only find one typeface that has both a static and a variable version: Roboto.

In our variable font performance test, we’ll compare the [static version of Roboto](https://fonts.google.com/specimen/Roboto) that you can download from Google Fonts and [Roboto Variable Font](https://github.com/TypeNetwork/Roboto), which you can find in TypeNetwork’s GitHub repository.

The static version of Roboto comes in 12 variations (the numbers stand for the `font-weight` value):

1. Thin (100)
2. Thin Italic (100)
3. Light (300)
4. Light Italic (300)
5. Regular (400)
6. Regular Italic (400)
7. Medium (500)
8. Medium Italic (500)
9. Bold (700)
10. Bold Italic (700)
11. Black (900)
12. Black Italic (900)

In variable font terms, it has 12 static font variations along two design axes: weight (`wght`) and italics (`ital`). On the other hand, the Roboto Variable Font includes three design axes: weight (`wght`), width (`wdth`), and slant (`slnt`).

To accurately compare the two font types, we should generate 12 variations of the Roboto Variable Font that are identical to the 12 variations of the static version. But while both versions include the `wght` axis, Roboto VF uses `slnt` instead of `ital`. Because of this, we’ll use the `slnt` design axis to generate the italic variants of the variable fonts. However, it’s important to remember that it’s not the same thing.

The [`ital`](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide#Italic) axis has a binary value (either 0 or 1). It can be accessed with either the high-level [`font-style`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-style) or the low-level [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) property. If both properties are available/supported, you should always use the high-level one, which is `font-style` here.

```jsx
font-style: italic;
font-variation-settings: 'ital' 1;
```

The [`slnt`](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide#Slant) axis typically ranges between 0 and 20 degrees. It can be accessed with the same CSS properties (`font-style` and `font-variation-settings`), but in a different way.

```jsx
font-style: oblique 12deg;
font-variation-settings: 'slnt' 12;
```

Since the `slnt` axis of the Roboto Variable Font ranges between 0 and 12, we will use its highest value (12) to create a slanted font variation that’s more or less comparable to the italic variation of the static version.

You might have also noted that the static version uses two design axes instead of three like Roboto VF. However, since these are only theoretical axes (I call them axes to make the two kinds of fonts comparable), this doesn’t skew the test result. Static fonts don’t include any axes; the characters are simply drawn without providing the user with any dynamic functionality.

## The test cases

We will use three test cases to analyze the performance trade-off of variable fonts. Each test case works with the same HTML page that consists of 12 “lorem ipsum” paragraphs, where each paragraph is displayed in a different variation of the Roboto font. The three test cases are:

1. Roboto Static Font with all its 12 variations (each font file pulled from Google’s CDN)
2. Roboto Static Font with all its 12 variations (each font file added locally)
3. Roboto Variable Font with 12 variations generated from a single variable font file that we add locally

In addition, we’ll explore a bonus test case with only four variations of the static version of the Roboto font.

You can find the entire performance test in this [GitHub repo](https://github.com/azaleamollis/variable-fonts-performance-tests) and run the tests by yourself on this [demo site](https://www.annalytic.com/variable-fonts-performance-tests/), where you can also find further information about the tests.

All test cases use the [WOFF2](https://developer.mozilla.org/en-US/docs/Web/Guide/WOFF) compressed font format and do not include any fallback for older browsers. Even though Roboto VF was available only in TTF format, I created a WOFF2 version using Google’s [woff2 CLI tool](https://github.com/google/woff2), which reduced its size from 3.36MB to 1.40MB.

For the performance tests, we’ll use two tools:

1. [GTMetrix](https://gtmetrix.com/), which calculates both PageSpeed Insights and YSlow scores
2. [Lighthouse](https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=es), which allows us to run performance audits in Chrome DevTools

### Test case 1: Roboto Static, hosted on Google CDN

We can pull Roboto Static from Google’s CDN by adding the following code to the `<head>` section of the HTML page.

```jsx
&lt;link href="https://fonts.googleapis.com/css?family=Roboto:100,100i,300,300i,400,400i,500,500i,700,700i,900,900i&amp;display=swap" rel="stylesheet"&gt;
```

The link specifies the font variations we want to load — for instance, 100 stands for Roboto Thin and 700i stands for Roboto Bold Italic. It’s easy to generate this custom link on [Google Fonts](https://fonts.google.com/specimen/Roboto?selection.family=Roboto:100,100i,300,300i,400,400i,500,500i,700,700i,900,900i) by selecting the variations under the Customize tab.

![Customizing Roboto on Google Fonts](https://www.dropbox.com/s/1yizxxh9nqpsfd5/generate-roboto-link-google-cdn.jpg?raw=1)

The link points to a [CSS file](https://fonts.googleapis.com/css?family=Roboto:100,100i,300,300i,400,400i,500,500i,700,700i,900,900i&display=swap) hosted on Google’s servers and includes a bunch of `@font-face` rules — 84, to be exact. Google Fonts adds a `@font-face` rule for each character set (Latin, Cyrillic, Greek, etc.), and it’s not possible to change this. However, Google Fonts only loads the font files that the page requests (in our case, the Latin character set).

Altogether, we pulled 84 `@font-face` rules and 12 WOFF2 files from Google’s CDN in this test case.

Note: If you run the performance test using an older browser, Google will load either the WOFF or TFF format for you — it always loads the most modern format that the user’s browser supports.

In addition, we have two local files — [`index.html`](https://github.com/azaleamollis/variable-fonts-performance-tests/blob/master/1-static-fonts-google-cdn/index.html) and `style.css` — on our server.

Now, let’s see how this setup performs. First, we’ll run the [demo page](https://www.annalytic.com/variable-fonts-performance-tests/1-static-fonts-google-cdn/index.html) for the first test case in the GTMetrix app.

![](https://www.dropbox.com/s/x9fs48rtyf4t3lt/gtmetrix-test-case-1.jpg?raw=1)

As you can see, we have a total page size of 197kB and 15 HTTP requests — 12 for the font files, one for `index.html`, one for `style.css`, and one for the online CSS file that contains the 84 `@font-face` rules.

The Lighthouse performance report looks like this:

![](https://www.dropbox.com/s/rfycai1vpjwd25z/lighthouse-test-case-1.jpg?raw=1)

The total performance score is 99, and the first contentful paint happened in 1.6 seconds. Let’s see how these results compare to the other test cases.

### Test case 2: Roboto Static, self-hosted

In this test case, we’ll work with the same `index.html` and `style.css` files. You can check out the files in the [GitHub repo](https://github.com/azaleamollis/variable-fonts-performance-tests/tree/master/2-static-fonts-self-hosted). However, this time we’ll add the `@font-face` rules manually. Since we want to load 12 font files, we’ll need 12 `@font-face` rules.

We’ll try to make it as similar to Google CDN’s (immutable) `@font-face` rules as possible, but we won’t add `@font-face` rules for character sets we don’t want to use. Even though this skews the test results a bit, no one would use these character sets on a real website, and our main goal is to determine which setup is better.

Let’s take a look at one of our `@font-face` rules (you can check out the entire [`fonts.css`](https://github.com/azaleamollis/variable-fonts-performance-tests/blob/master/2-static-fonts-self-hosted/fonts.css) on GitHub):

```jsx
@font-face {
    font-family: 'Roboto';
    font-style: normal;
    font-weight: 100;
    font-display: swap;
    src: local('Roboto Thin'), local('Roboto-Thin'),
         url('fonts/roboto-v20-latin-100.woff2') format('woff2');
     unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }
```

As you can see, we placed the 12 WOFF2 font files into the [`fonts/`](https://github.com/azaleamollis/variable-fonts-performance-tests/tree/master/2-static-fonts-self-hosted/fonts) folder.

Here’s what GTMetrix returned:

![](https://www.dropbox.com/s/l9namw2ffvjvnn0/gtmetrix-test-case-2.jpg?raw=1)

Both the page load time (0.7s) and the number of HTTP requests (15) are the same as in the previous case. However, the total page size is 1KB smaller, which must be the result of the reduced number of `@font-face` rules (12 instead of 84).

Lighthouse’s performance audit resulted in the following metrics.

![](https://www.dropbox.com/s/mf4m077cca2gl6a/lighthouse-test-case-2.jpg?raw=1)

The first contentful paint took just 1.2s, down from 1.6s, a 25 percent improvement. Consequently, Lighthouse’s performance score is also a bit higher: 100 instead of 99. This is most likely because Google Fonts runs a few checks to decide which font format/file to load, while our self-hosted CSS contains static file paths.

### Test case 3: Roboto Variable Font, self-hosted

In the third test case, we’ll analyze the performance of the Roboto Variable Font using the same [`index.html`](https://github.com/azaleamollis/variable-fonts-performance-tests/blob/master/3-variable-fonts/index.html) file as before. The [`style.css`](https://github.com/azaleamollis/variable-fonts-performance-tests/blob/master/3-variable-fonts/style.css) file is nearly identical, but, as mentioned earlier, the italic effect is achieved by using the slant axis since Roboto VF doesn’t have a design axis for italics.

We’ll load `fonts.css` locally, similar to the second test case, except now it contains only one `@font-face` rule.

```jsx
@font-face {
        font-family: 'Roboto VF';
        font-weight: 100 900;
        font-stretch: 75% 100%;
        font-style: oblique 0deg 12deg;
        font-display: swap;
        src: local('Roboto VF'), local('Roboto-VF'), 
             url('fonts/Roboto-VF.woff2') format('woff2-variations');
        unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;  
}
```

We defined the available ranges of all three design axes found in Roboto VF. This is also the recommended way of adding variable fonts (see the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide#Using_a_variable_font_font-face_changes) for more details).

The `font-weight` property stands for the `wght` axis and spans from 100 to 900. `font-stretch` stands for the `wdth` axis and spans from 75 percent to 100 percent — we won’t use this axis since Roboto Static doesn’t have variants for different font widths. `font-style: oblique;` stands for the `slnt` axis and spans from 0deg to 12deg (we use this axis with its maximum value instead of italics).

Note that in production, we would use this `@font-face` rule inside a [`@supports`](https://developer.mozilla.org/en-US/docs/Web/CSS/@supports) feature query and add Roboto Static (or another font) as a fallback, since many browsers still don’t [support variable fonts](https://caniuse.com/#feat=variable-fonts). This somewhat distorts the test results because we’re working with a smaller `fonts.css` file than we would in production. However, as already mentioned, it’s impossible to compare static and variable fonts with 100 percent accuracy due to their different nature.

For the third test case, the GTmetrix tool returned the following result.

![](https://www.dropbox.com/s/czctjkgf6ghsfbc/gtmetrix-test-case-3.jpg?raw=1)

The number of HTTP requests decreased drastically, from 15 to four. This is because we’re working with only one font file instead of 12. On the other hand, the total page size grew markedly, from 197/196KB to 1.41MB, which is due to the huge size of the variable font file.

How do these two values balance each other out? Given that the total page load time shrank from 700ms to 490ms — a 30 percent improvement — it seems that switching to a variable font was a good choice in this case.

The Lighthouse performance audit also shows improved performance metrics.

![](https://www.dropbox.com/s/ujszg1p33dewg36/lighthouse-test-case-3.jpg?raw=1)

The first contentful paint happened twice as fast as in the first test case (0.8s compared to 1.6s), and 1.5 times faster than in the second test case (0.8s compared to 1.2s).

Judging by these test results, using a variable font is a good choice when you want to load all 12 variations of the static version of Roboto. Although the total font size and page size are much bigger, the significant decrease of HTTP requests (four compared to 15) still results in a better page load time.

### Bonus test case

An important question arises here: at what point is it no longer worth using variable fonts? To answer this, we’ll look into one additional test case.

This test case is almost identical to the first one. We’ll load Roboto Static from Google’s CDN and add `index.html` and `style.css` locally. However, instead of adding all 12 static variations, we’ll use only four: Roboto Light, Roboto Regular, Roboto Regular Italic, and Roboto Bold. The [`index.html`](https://github.com/azaleamollis/variable-fonts-performance-tests/blob/master/additional-test-case/index.html) file still consists of the same 12 same paragraphs, but we’ll use the same font variation on three paragraphs instead of one.

The following `<link>` tag will load the four font variations.

```jsx
&lt;link href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700&amp;display=swap" rel="stylesheet"&gt;
```

Let’s see how this additional test case performed in GTmetrix:

![](https://www.dropbox.com/s/xeol7c3jk5x5w47/gtmetrix-test-case-additional.jpg?raw=1)

As expected, the number of HTTP requests shrank from 15 to seven since we loaded four font files instead of 12. Obviously, the total page size is also much smaller than in the first test case (66.3KB versus 197).

The total page load time is much faster than in any of the previous test cases. In the first two test cases, it was 700ms, while the Roboto Variable Font loaded in 490ms. This time around, the page loaded in just 301ms.

But, what does the Lighthouse performance audit say?

![](https://www.dropbox.com/s/kolnh7kqey6hv2o/lighthouse-test-case-additional.jpg?raw=1)

The first contentful paint was 1.6s, which is the same result as in the first test case and worse than both the second (1.2s) and third (0.8s). This is most likely because the fonts were downloaded from a CDN instead of locally, rather than using a static font instead of a variable one or the number of HTTP requests.

All in all, since the total page load time is much faster than in the case of variable fonts, we can say that using Roboto VF is not worth it if you want to use/load only four font variations.

## Conclusion

Before drawing a final conclusion, let’s see the results side by side:

![Chart Comparing the Results of the Four Test Cases](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2020/03/variable-static-fonts-performance-test-results.png?resize=730%2C283&ssl=1)

Whether using variable fonts is worth it performance-wise depends on how the decrease in HTTP requests and the increase in total page size balance each other out.

If you want to use several variations of the same typeface, using variable fonts is definitely a good option. However, if you want to use a font in an ordinary way — for instance, the bold, italic, and bold italic variations — you may want to stick with the static version.

Right now, the performance trade-off of variable fonts is more of a theoretical question than a practical one. Since the vast majority of fonts don’t have both a static and a variable version, in reality, we don’t usually have a choice. However, this is poised to change in the future as variable fonts develop and improve.

Finally, don’t forget that the performance aspect is only one consideration when evaluating the usefulness of variable fonts. Design flexibility is just as important. Variable fonts push the limits of web typography to the next level, allowing us to create website designs we never thought possible.

* * *
## Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, [try LogRocket.](https://logrocket.com/signup/) 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/403rye2ptzx994uhktk1.png)

[LogRocket](https://logrocket.com/signup/) is like a DVR for web apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web apps — [Start monitoring for free.](https://logrocket.com/signup/)
* * *

The post [Variable fonts: Is the performance trade-off worth it?](https://blog.logrocket.com/variable-fonts-is-the-performance-trade-off-worth-it/) appeared first on [LogRocket Blog](https://blog.logrocket.com).