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.
π 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.