Beginner's Guide to Variable Fonts: Part 2

Step-by-step guide on how to use variable fonts in your projects.

In Part 1 of our Beginners' Guide to Variable Fonts, we explained how variable fonts work behind the scenes and why you may want to incorporate them in your projects. Now let’s dive into how you too can easily start using variable fonts in five fool-proof steps!

To better understand each step and nail down key concepts, we will code a section of this mini variable fonts build together.

Coding Variable Fonts Steps

1. Experiment with variable fonts and download files (or links).

There are a handful of websites that serve as both repositories and playgrounds for you to experiment with variable fonts. The most popular of these are Axis-Praxis, Variable Fonts (beta), and Font Playground. To download the variable font file(s) of your choice on these sites, you will most likely need to go to or be directed to the font designer’s website or Github page.

For our design, we need two variable fonts: Jabin by Frida Medrano and FF Meta Variable Demo by Monotype Imaging Inc. Let’s head over to Axis-Praxis to download Jabin together! Take a moment to familiarize yourself with the site. You can see under "Font Variations" on the right column that Jabin has two axes: weight and an unnamed Custom axis (note that the width axis has a range of 0 to 0 so it is not a working axis). Go ahead and move the range sliders for the weight and Custom axes to see these two axes interpolate in real time. Pretty cool! When we click on the information icon, a font info modal pops up that houses all the information you need to know about the font. This includes the registered and custom axes ranges and the URL Vendor where you will need to go to download the Jabin typeface files. Once you’ve downloaded the files, let’s move on to step two!

2. Set up variable fonts with @font-face.

Now in our CSS file, we can set up our fonts as we normally would using the @font-face rule. Depending on availability, this means using a variable font file or a file link just like we do with standard or Google fonts. Since we downloaded a woff2 file for Jabin, we simply linked to that file in our project. Notice that we set our variable font format to woff2-variations, woff2, and woff for practical support in all major browsers. MDN’s variable fonts guide notes that “all browsers that support variable fonts will still render them if you set the format to just the file format, rather than format-variations (i.e. woff2 instead of woff2-variations), but it’s best to use the proper syntax if possible.”

The main difference between setting variable fonts and standard fonts is that we need to define the range for the variable font’s registered axes variations. Remember that Jabin has two axes: weight and Custom. We don’t need to set a range for our Custom axis here but we need to for weight. We use the font-weight property to set Jabin’s weight axis range (see Part 1 for a list of all registered axes properties). For our animation, we wanted to be able to interpolate our code between the lowest (40) and highest (120) defined values for our weight axis. So, the first number is the lowest value and the second number, the highest of our declared range. Note that you can also set the lowest and highest range as any number between 40 and 120 - the choice is yours!

Out of extra caution, we are setting the font-display property value as fallback. This makes the custom font styled text invisible for an extremely small block period of time. While custom fonts load, the unstyled text will appear. Once the custom font loads, the text is styled with our variable font styles.

/* Variable Fonts */

@font-face {
  font-display: fallback;
  font-family: 'Jabin VF';
  font-weight: 40 120;
  src: url('../fonts/Jabin.woff2') format('woff2-variations'),
    url('../fonts/Jabin.woff2') format('woff2'),
    url('../fonts/Jabin.woff') format('woff');
}

3. Set up fallback fonts with @font-face.

In just under 3 years since their debut, variable fonts have reached a whopping 84% global browser support (June 2019), which is a relatively quick adoption rate! So, we only have to worry about providing fallback fonts in the form of static or Google fonts for Internet Explorer 11 and older browsers that don’t support variable fonts.

When choosing our fallback fonts, we pick static fonts that resemble our variable fonts in appearance and voice. We decided on Cormorant Garamond for our fallback Google font for Jabin. Again, we used the @font-face rule, this time to declare Cormorant Garamond font weight and respective files in our project.

/* Fallback Google Fonts */

@font-face {
  font-family: 'CG';
  font-style: normal;
  font-weight: 700;
  src: url('../fonts/CormorantGaramond-Bold.woff2') format('woff2-variations'),
    url('../fonts/CormorantGaramond-Bold.woff2') format('woff2'),
    url('../fonts/CormorantGaramond-Bold.woff') format('woff');
}

4. Declare variable font variation values.

Font-variation-settings is the property we have to use to control variable font characteristics. This is where we specify the four-letter axes names we want to set and their values.

As we discussed in Part 1, the four-letter axes names for registered axes are the same across variable fonts and always lowercase letters. Custom axes names are defined by the typeface designer and are always uppercase letters.

If we ever forget the registered or custom axes names for our chosen variable fonts, all we need to do is reference the Font info on Axis-Praxis. Let’s look again at the axes information for Jabin. Voila. We will use wght for the weight axis and XXXX for the Custom axis.

We can set one or as many axes as we want by separating them with commas. Since we defined a low and high range for Jabin’s registered weight axis, we can set the weight value as any value we wish within that range.

.letter {
    font-family: 'Jabin VF', sans-serif;
    font-variation-settings: 'wght' 700, 'XXXX' 0;
    font-weight: 700;
  }

5. Code fallback fonts and use CSS @supports feature queries.

For faster performance, we want browsers that support variable fonts to only download the variable font files and unsupported browsers to only download the fallback static font files. The @supports feature query makes that possible.

First, we style your element using the fallback Google font we declared earlier (Cormorant Garamond). Here we declare the font-family and other variations such as font-weight or font-style as we normally would. This takes care of our fallback styles.

Next we take our font variation styling code from Step 4 and wrap inside an @supports rule. Remember to always place variable font styles code after fallback styles to comply with CSS cascading rules.

.letter {
  color: rgba(255, 255, 255, 0.15);
  font-family: 'CG', sans-serif;
  font-size: 200px;
  font-weight: 700;
  margin: 0;
  text-transform: uppercase;
}

@supports (font-variation-settings: normal) {
  .letter {
    font-family: 'Jabin VF', sans-serif;
    font-variation-settings: 'wght' 700, 'XXXX' 0;
    font-weight: 700;
  }
}

Now you may be wondering, why go through all the trouble of using additional @supports statements? Can’t we just use the normal CSS font-family cascade to mix and match font-family usage more easily and reduce our code? For example, do something like this:

font-family: 'Jabin VF', CG, sans-serif;

What a great question! You can… but don’t. While this method may seem “simpler” because it is shorter, it allows some browsers to download all declared fonts rather than just the supported ones.

Bonus. Animate variable fonts.

Variable fonts have so many cool features and one of these is animation. We wanted to show you how easy it is to animate variable fonts. For our example, we simply gave our variable fonts styling block an animation property where we call the @keyframes slide. This @keyframes slide alternates infinitely between the lowest and highest ranges of Jabin’s weight and Custom axes.

.letter {
  color: rgba(255, 255, 255, 0.15);
  font-family: 'CG', sans-serif;
  font-size: 200px;
  font-weight: 700;
  margin: 0;
  text-transform: uppercase;
}

@supports (font-variation-settings: normal) {
  .letter {
    animation: slide 3s infinite alternate;
    font-family: 'Jabin VF', sans-serif;
    font-variation-settings: 'wght' 700, 'XXXX' 0;
    font-weight: 700;
  }

  @keyframes slide {
    0% {
      font-variation-settings: 'wght' 700, 'XXXX' 100;
    }
    100% {
      font-variation-settings: 'wght' 40, 'XXXX' 0;
    }
  }
}

variable fonts text animation

And that’s it. We’re done! In just a few small steps we were able to give our build a unique and fun voice using variable fonts. To see what all the steps look like when put together, please see this repo.

Drawbacks

We noticed a few drawbacks while coding variable fonts that are worth mentioning. First, we still have to use fallback fonts for Internet Explorer and older browsers. While not a significant hurdle, it can make the coding process more time consuming. Second, fallback fonts should ideally look like variable fonts, if there isn’t a regular version of the variable font. This is so that users can experience the same voice on different browsers. Finding similar looking variable and regular fonts may be difficult to do at times. Lastly, if the variable fonts are being animated, the animations must not be crucial for comprehending the content since these animations will not be active on browsers that don’t support variable fonts.

Final Thoughts

Overall, we see variable fonts as a step in the right direction in making design translate seamlessly to the web. Variable fonts allow us to have all the fonts variations and styles we need in one compact file - and the benefit of having a fonts API that we can manipulate and animate using smaller files. It is breaking down barriers that web limitations have imposed for quite a while. The biggest limitation now are the design tools and browsers we use to create engaging beautiful websites.

Ola Assem

Ola is a researcher-turned-front-end developer in our Boulder, CO office. She enjoys morphing functionality and accessible user design thinking into digital experiences.

More articles by Ola