All Articles

Variable Fonts

Variable Font

Variable fonts are increasing in popularity as the browser support is getting better by the day. A single font file for multiple styles.

Introduction

Traditionally, a font file has to be served for every member of a typeface family. Having thin, regular, bold & italic styles for several different weights will add up fast and you may end up with several hundred KBs of data.

Variable fonts, however store multiple variants of a typeface family in a single font file. This article will use Inter, which is a free and open-source font family that offers both Traditional constant font files and a Variable font file.

πŸš€ Adding Variable font Inter to a React App

This article assumes that the project is based on Create React App.

Using CSS imports

Use the webpack build pipeline to include the font file in the final bundle by using import in a JavaScript module. No need to worry about long-term caching of assets as webpack creates the final filename based on the content hash of the compiled bundle.

You should already have the following line in src/index.js:

import "./index.css";

First, download the Inter typeface family from the official Inter page. The download link is found in the top navigation menu.

Simplified tree of the downloaded zip:

β”œβ”€β”€ Inter Desktop
β”‚Β Β  └── ...
β”œβ”€β”€ Inter Hinted for Windows
β”‚Β Β  └── ...
β”œβ”€β”€ Inter Variable
β”‚Β Β  └── ...
β”œβ”€β”€ Inter Web
β”‚Β Β  β”œβ”€β”€ ...
β”‚Β Β  β”œβ”€β”€ Inter-ThinItalic.woff
β”‚Β Β  β”œβ”€β”€ Inter-ThinItalic.woff2
β”‚Β Β  β”œβ”€β”€ Inter-italic.var.woff2
β”‚Β Β  β”œβ”€β”€ Inter-roman.var.woff2
β”‚Β Β  β”œβ”€β”€ Inter.var.woff2
β”‚Β Β  └── inter.css
└── ...

Extract inter.var.woff2 from the Inter Web folder. Create a fonts folder into the project src and move the font file inside of it.

Next, let’s add the following @font-face rule to src/index.css

@font-face {
  font-family: "Inter Variable";
  src: url("./fonts/Inter.var.woff2") format("woff2");
  font-weight: 100 900;
}

To make use of the variable weight axis the range of font-weight is set to be from 100 to 900. When font-weight is omitted, it’s treated with a default value of font-weight: 400 by the browser. Meaning that the font would correspond to only 400 weight regardless of it being a variable font.

Finally, apply the font to a DOM element and try it out!

body {
  font-family: "Inter Variable", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

Notice that font-smoothing property is also added to make font rendering a bit nicer in WebKit and Firefox based browsers.

End Result

πŸŽ‰ That’s it. The font-weight can be set to any value between 100 and 900.

You can even have some fun and animate between the font weights or any other font-variation-settings value supported by your font family.

// index.css

@keyframes breathe {
  0% {
    font-weight: 100;
  }

  50% {
    font-weight: 900;
  }

  100% {
    font-weight: 100;
  }
}

h1 {
  animation: breathe 2000ms infinite;
}

Don’t recommend using this in production as it causes repaints πŸ˜…

Using the public folder

It’s also possible to edit public/index.html and add a link to the index.css stylesheet via the traditional way. The %PUBLIC_URL% variable will be replaced with the URL of the public folder during build time.

CRA docs - Using the Public Folder

<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%/index.css" />

Create a fonts folder in the public folder with the downloaded variable font file inside of it.

Next, put the following content into a new file in public/index.css

@font-face {
  font-family: "Inter Variable";
  src: url("fonts/Inter.var.woff2") format("woff2");
}

Done! Now just use font-family to apply it as shown in the previous section.

When possible, prefer the CSS import method as this avoids the webpack build pipeline, which means that the index.css doesn’t get minified, hashed, etc.

Supporting older browsers

The browser support for Variable fonts is getting better, as of writing this (July 2020) it’s over 90%.

Fallback code

Extract all the files from Inter Web to the project src/fonts folder (similarly to the CSS import section).

Add @font-face rules like the one below from Inter Web/index.css to your index.css. These will refer to traditional font files for fallbacks. Avoid importing font styles that you don’t plan on using.

@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/Inter-Regular.woff?v=3.13") format("woff");
  src: url("fonts/Inter-Regular.woff2?v=3.13") format("woff2");
}

IE11 doesn’t support Web Open Font Format 2.0 .woff2 and needs .woff fallback.

All browsers that support Variable fonts also support CSS Feature Queries. So it’s possible to check if the feature is supported using @supports and then override the fallback styling.

body {
  font-family: "Inter", sans-serif;
}

@supports (font-variation-settings: normal) {
  body {
    font-family: "Inter Variable", sans-serif;
  }
}

Alternatively you can use the following CSS from Inter to get everything remotely with fallbacks. However, using a subset of inter.css styles locally is preferred.

@import url("https://rsms.me/inter/inter.css");

body {
  font-family: "Inter", sans-serif;
}

@supports (font-variation-settings: normal) {
  body {
    font-family: "Inter var", sans-serif;
  }
}

Font variation settings

Each font family defines their own font-variation-settings that change the font in different ways.

There’s a great resource v-fonts for trying and discovering Variable fonts with sliders for their custom settings.

References