CSS font-variation-settings and Custom Axes Guide
The font-variation-settings property in CSS provides
low-level control over variable font features by directly manipulating
the font's underlying OpenType axes. While modern CSS includes
dedicated, high-level properties for standard axes—such as
font-weight for wght or
font-stretch for wdth—the
font-variation-settings property remains essential for
accessing and fine-tuning custom, proprietary axes defined by font
creators.
Understanding
font-variation-settings
Variable fonts contain one or more axes of variation that allow a
single font file to behave like multiple distinct font instances. The
font-variation-settings property provides a mechanism to
set these axes using a key-value syntax, where the key is a
case-sensitive, four-character OpenType tag and the value is a numeric
variable within that axis’s supported range.
selector {
font-variation-settings: 'tag1' value, 'tag2' value;
}Standard Axes vs. Custom Axes
OpenType specifications divide axes into two distinct categories:
Standard (Registered) Axes: Standardized axes that have universal meanings across all fonts. They are identified by four lowercase characters:
'wght'(Weight)'wdth'(Width)'slnt'(Slant)'ital'(Italic)'opsz'(Optical Size)
W3C specifications recommend using standard CSS properties (
font-weight,font-stretch,font-style, andfont-optical-sizing) instead offont-variation-settingswhen targeting standard axes to ensure semantic correctness and proper accessibility mappings.Custom (Vendor-Specific) Axes: Proprietary variations designed by a type foundry for a specific typeface. Common examples include grade, serif size, flare, or roundness. Custom axes are identified by four uppercase characters, distinguishing them from registered axes.
Implementing Custom Axes
To use a custom axis, inspect the variable font's metadata or foundry
documentation to identify the four-character uppercase tag and its
allowed numerical range (e.g., 0 to 100, or
-1 to 1).
For instance, the font Recursive includes custom axes such as Casual
('CASL') and Cursive ('CRSV'). You target them
directly through font-variation-settings:
.casual-heading {
font-family: 'Recursive', sans-serif;
font-weight: 700; /* Standard axis handled by standard property */
font-variation-settings: 'CASL' 1, 'CRSV' 0.5; /* Custom axes */
}Another widespread custom axis is Grade ('GRAD'), used
to adjust the optical weight of text without changing its physical
metrics or layout boundaries:
.dark-mode-text {
font-family: 'Roboto Flex', sans-serif;
font-variation-settings: 'GRAD' -0.5;
}Animating and Transitioning Custom Axes
Because values declared in font-variation-settings are
numerical, custom axes can be animated or transitioned smoothly using
standard CSS transitions and keyframes:
.interactive-button {
font-family: 'ExampleVariableFont', sans-serif;
font-variation-settings: 'FLAR' 0;
transition: font-variation-settings 0.3s ease-in-out;
}
.interactive-button:hover {
font-variation-settings: 'FLAR' 100;
}The Inheritance Caveat
The primary drawback of font-variation-settings is that
it acts as an all-or-nothing property; it does not cascade on an
axis-by-axis basis. If a child element defines
font-variation-settings to modify one axis, it overrides
and resets all other custom axes declared on parent elements unless they
are explicitly re-declared.
To avoid unintended resets, manage custom axes using CSS custom properties (variables):
:root {
--axis-casl: 0;
--axis-crsv: 0;
}
body {
font-family: 'Recursive', sans-serif;
font-variation-settings: 'CASL' var(--axis-casl), 'CRSV' var(--axis-crsv);
}
.playful {
--axis-casl: 1;
}By binding custom axes to CSS variables, individual axes can be updated modularly without wiping out other declared variations in the cascade.