TL;DR: A variable font packs an entire typeface, with every weight, width and style in between, into a single file. Instead of loading separate files for regular, bold and italic, you load one file and pick any point along its “axes” with CSS. Done right, variable fonts give designers far more typographic control and can cut the number of font requests on a page. This guide explains how they work, the five standard axes, the CSS you need, and the mistakes to avoid.
What is a variable font?
For most of digital typography’s history, each style of a typeface lived in its own file. Roboto Regular, Roboto Bold and Roboto Bold Italic were separate fonts, and a full family could easily run to 20 or 30 files. On the web, that meant every extra weight was another download.
Variable fonts change that model. They are part of the OpenType font specification, introduced in version 1.8 in 2016 through a joint effort by Apple, Google, Microsoft and Adobe, and Microsoft documents the technical details in the OpenType specification. As MDN’s variable fonts guide puts it, they let “many different variations of a typeface” be incorporated into a single file. A variable file is bigger than one static font, but MDN notes it is usually about the same size as, or smaller than, the four static files most sites load for body text.
How variation axes work
The core idea is the axis of variation. Each axis describes a range a designer has built into the font. A weight axis might run from hairline thin to ultra black. A width axis might run from condensed to extended. You can choose any value along that range, not just the handful of presets a static family offers.
There are two kinds of axes:
- Registered axes are standardized in the specification and map to familiar CSS properties.
- Custom axes are anything a type designer invents, identified by a four-letter tag in capital letters, such as
GRADfor grade.
The five registered axes
| Axis | Tag | Preferred CSS property | Typical values |
|---|---|---|---|
| Weight | wght | font-weight | Any number from 1 to 1000, within the font’s range |
| Width | wdth | font-stretch | Percentages, often around 75% to 125% |
| Italic | ital | font-style: italic | 0 (off) to 1 (on) |
| Slant | slnt | font-style: oblique | An angle, for example 0 to 12 degrees |
| Optical size | opsz | font-optical-sizing | auto or none |
Optical size is the most interesting newcomer. It revives an old metal-type practice where small sizes got sturdier strokes and large sizes got more contrast. With font-optical-sizing: auto, the browser adjusts the design to match the font size automatically.

How to use a variable font in CSS
Step 1: Load it with @font-face
The main difference from a normal web font is that you declare ranges instead of single values:
@font-face{
font-family: "MyVariable";
src: url("/fonts/my-variable.woff2") format("woff2-variations");
font-weight: 100 900;
font-stretch: 75% 125%;
font-style: normal;
font-display: swap;
}MDN points out that not every browser understands the full format syntax, but browsers that support variable fonts will still load them if you simply write format("woff2").
Step 2: Use standard properties first
Once loaded, you can use any value in range:
h1 { font-weight: 780; font-stretch: 88%; }
p { font-weight: 380; font-optical-sizing: auto; }The W3C’s intent, according to MDN, is that you use these high-level properties whenever possible and only reach for the lower-level syntax when you need something they can’t express.
Step 3: Reach for font-variation-settings for custom axes
Custom axes, such as grade, need font-variation-settings:
.button:hover { font-variation-settings: "GRAD" 150; }Two rules trip people up. Axis tags are case-sensitive: registered axes are lowercase and custom axes are uppercase. And when you change one value, you have to redeclare every axis in that rule. A common workaround is to store each axis in a CSS custom property, then update only the variable you need.
Where variable fonts shine in design
- Fine-tuned hierarchy. Headings, subheadings and body text can each get a slightly different weight and width, the way print magazines have long done with 10 to 15 style combinations.
- Responsive typography. Narrow the width on small screens to fit longer headlines without shrinking the text.
- Dark mode. Text often looks heavier on dark backgrounds. A grade axis lets you thin it slightly without changing letter spacing or causing the layout to reflow.
- Interaction states. Animate weight or grade on hover for subtle feedback, again without moving surrounding elements when you use grade.
- Brand systems. One file can serve an entire design system, from data-dense dashboards to big marketing headlines.
Where to find good variable fonts
Google Fonts lets you filter its library to show only variable fonts, and families like Roboto Flex, Inter and Recursive show how many axes a single file can carry. For exploring what a particular file can do, MDN recommends tools such as Wakamai Fondue, which lists a font’s axes and features when you drop the file in, and the V-Fonts catalog.
Common mistakes to avoid
- Loading a variable font and a static font of the same family. You lose the size savings and risk mismatched rendering.
- Letting the browser fake styles. Add
font-synthesis: noneso the browser doesn’t apply a synthetic italic or bold on top of the real one. - Skipping ranges in @font-face. Without them, the browser may not know which weights the file covers.
- Using too many axes at once. Just because you can vary everything doesn’t mean you should. Pick a few values and turn them into design tokens.
- Forgetting older systems. MDN notes that old operating systems, such as macOS before High Sierra, lack support. Use an
@supportsquery to serve a static fallback where it matters.
Browser support is now broad across current versions of Chrome, Edge, Firefox and Safari; you can check the details on Can I Use.
The bottom line
Variable fonts are one of the rare design upgrades that improve both creative control and technical efficiency. Start by replacing a multi-weight static family with its variable version, declare proper ranges in @font-face, and use standard CSS properties before touching font-variation-settings. Once that works, experiment with width and optical size, and you’ll find typography on the web can finally feel as refined as it does in print.


