What are variable fonts and how to use them on the web

When we build a website, we need some variations of a font: a bold style version for headers, a regular version for body text, italic variation for some small details, a condensed version sometimes, and so on. Usually, for each of these versions, we need to load a separate font file: AwesomeFontBold.woff2, AwesomeFontRegular.woff2, AwesomeFontItalic.woff2 etc.

A single file can also be used for all variations, in which case the browser will synthesize a missing style, but it produces suboptimal results. If you ever worked with a UX designer, you know they will not be happy.

So to make the UX happy and make a great website copy we use different font files. But we soon enter a rabbit hole: What if we also need a condensed bold version and an expanded italic version? Do we load two new font files?

There is a solution to this issue: one font to rule them all, a special type of font that supports any variation we need. A font that can be used from ultra light weight to a strong bold weight. That can be used condensed or expanded. That font is called a variable font. A variable font is a font that supports a lot of variations using a single font file. It has all the styles built in a single file.

Note: since the introduction of variable fonts, the non-variable fonts are now called “static” or “standard” fonts. I’ll use this term too.

Here is a quick demo of how variable fonts work:

When to consider variable fonts?

The downside of the variable font file is that is much bigger than the size of a standard single-style file. You need to do some math and decide if standard fonts are sufficient.

If you only use bold, regular, and italic versions of a font, this means you load 3 files, assuming a size of 20Kb each, you’ll load 60Kb. If the variable font file is 300Kb - 5x the size of the others - it’s not worth using the variable font. Use your own judgment based on your needs.

When you compare non-variable fonts with variable fonts make sure you compare the same type of fonts, e.g. TTF with TTF, WOFF2 with WOFF2. For websites always use the WOFF2 version of the fonts as it provides the best compression available these days.

In case you can only find the TTF version of a font (many font makers provide only TTF format) you should convert it to WOFF2. There are different ways to do this but you need to be careful when converting variable fonts as some converters will make the font standard (non-variable.)

To convert use the following steps:

  1. First, check if a font is variable using a tool like https://wakamaifondue.com/

  2. Then, use a converter (like https://everythingfonts.com/ttf-to-woff2) to convert the TTF(or OTF, or WOFF) to WOFF2. Download the converted WOFF2 font.

  3. Finally, check again if the converted font is still variable (using https://wakamaifondue.com/)

Note: Another way to optimize the variable fonts (and standard fonts) is by removing the glyphs you don’t use. Most of the fonts provide glyphs for a lot of alphabets, like Latin, Cyrillic, Japanese, etc. If your website renders copy using only Latin glyphs, the non-Latin glyphs are loaded for no reason. See Reduce web font size for more details.

Leaving the file size issue aside, variable fonts allow something that was incredibly hard before, magazine-level typographic techniques. (It is typical in a typographic system for a magazine to use 10–15 or more different weight and width combinations throughout the publication) For us developers, this ain’t much, but is a godsend feature for UX designers who spend hours setting the perfect size, weight, and width for each piece of copy.

Where we can find variable fonts?

Google Fonts

Google Fonts has a big selection of variable fonts. Sadly, the GDPR-safe alternative - Bunny fonts doesn’t provide a way to filter for variable fonts.

Variable fonts

Variable fonts is another big collection of variable fonts. There are some fonts free for commercial use, you can filter the fonts by license.

Abobe Fonts

You can find a lot of variable fonts on Adobe Fonts too. If you’re using the Adobe products this can be useful as most of them have support for variable fonts now.

Font foundries/makers

Many font makers are providing both standard and variable versions of the same fonts. Here is a beautiful example of Hatton font.

Using variable fonts

Just as with standard fonts, @font-face is used with variable fonts. With a few small differences…

@font-face {
	font-family: 'BDOGrotesk';
	src: url('/fonts/BDOGrotesk-VF.woff2') format('woff2-variation');
	font-weight: 300 900;
	font-display: swap;
}

The above example used the BDOGrotesk variable font. The format is not “woff2” but “woff2-variation” and also the font-weight is not a single value but a range.

Variable font axes

The things that are variable in the font are called “axes”. There can be registered axes and custom axes. Registered axes are common enough that they were standardized.

Registered axes’ names are spelled lowercase while the custom axes’ names are spelled uppercase. For registered axes there are CSS properties, for custom, there are not - so changing the custom axis values is a bit more complicated…

Note: Not all fonts have all the axes. A font is variable if it has at least one axis! Most fonts have only one or two axes, some have a lot more axes — for example, Roboto Flex has 13 axes! You can use a tool like https://wakamaifondue.com/ to check what axes are available for a particular font.

Registered/Standardized axes:

  1. weight (wght) / font-weight: sets the weight (or boldness) of the font.
  2. width (wdth) / font-stretch: sets how narrow or wide (condensed or extended, in typographic terms) the letterforms can be.
  3. slant (slnt) / font-style: oblique: sets the angle of the letterforms but doesn’t perform any kind of character substitution.
  4. italic (ital) / font-style: italic: ital axis can be set in the range [0-1], where 0 specifies “not italic,” 0.5 specifies “halfway italic,” and 1 specifies “fully italic.”
  5. optical size (opsz) / font-optical-sizing: sets the overall stroke thickness of letterforms.

font-variation-settings

There are no CSS properties for custom axes, but there is a special new property that can be used to set values for custom axes: “font-variation-settings”

font-variation-settings: 'CONT' 100, 'MIDL' -200;

You can use “font-variation-settings” to set registered axes too. For example, for the weight axis, we can use the “wght” setting:

font-variation-settings: 'wght' 100;

Tip: In case you set both font-weight and font-variation-settings ‘wght’, the wght value always wins! font-variation-settings always win!

h1 {	
	font-variation-settings: 'wght' 800; 
	font-weight: 600;
}

It’s a common practice to use font families with variable axis settings. Using CSS Variables we can overwrite each axis if needed:

:root {
	--font-weight-regular: "wght" 400;
	--font-weight-medium: "wght" 500;
	--font-weight-bold: "wght" 700;

	--font-size-small: "opsz" 16;
	--font-size-medium: "opsz" 20;
}

@font-face {
	font-family: 'BDOGrotesk';
	src: url('/fonts/BDOGrotesk-VF.woff2') format('woff2-variation');
	font-display: swap;
}

h1 {
	font-family: 'BDOGrotesk';
	font-variation-settings: var(--font-weight-bold) var(--font-size-medium); 
}

/* wght axes will change, but opsz with stay the same */
h1.secondary {
	--font-weight-bold: "wght" 800;
}

font-variation-settings allows greater control over the values, for example for optical size font-optical-sizing allows only auto/none while opsz allows a numeric value from a range.

Fallbacks

Browser support for variable fonts is excellent, but as a precaution, you can use static fonts as a fallback using the @supports at-rule.

@font-face {
	font-family: 'BDOGrotesk';
	src: url('/fonts/BDOGrotesk-VF.woff2') format('woff2-variation');
	font-weight: 300 900;
	font-display: swap;
}

@font-face {
	font-family: 'BDOGrotesk-Static';
	src: url('/fonts/BDOGrotesk.woff2') format('woff2');	
	font-display: swap;
}

h1 {
	font-family: 'BDOGrotesk-Static'; /* standard font version */
}

@supports (font-variation-settings: "wght" 415) {
  h1 {
	 font-family: 'BDOGrotesk'; /* variable font version */
	 font-variation-settings: 'wght' 415;
  }
}

Resources

Want to learn more?