Variable Fonts
16 Jan 2019
How to Implement
Variable Fonts
on the Web
This article aims to discuss what to consider when implementing variable fonts on the web, as well as how to add variable fonts to a website.
Variable fonts are at the time of writing supported in most major browsers, and available for approximately 78% of all users. Hence, there are no excuses for not taking advantage of the technology.
If you need a quick refresh on the subject, have a look at our blog post “Variable Fonts on the Web” for an overview of variable fonts.
Performance
Subsetting
Variable font files tend to get rather large since they are containing a lot of data for different font variations. The most common practice seems to be subsetting the font if that is feasible. A word of warning though, it seems that a lot of the tools used for creating font subsets also sometimes removes data that is needed to keep the variable parts of the font data.
The tool Glyphhanger is said not to remove any unnecessary data when subsetting variable fonts. Fonttools is another alternative.
woff2
Converting the file to woff2 format is also a way of trying to keep it as light-weight as possible. One of many tools for the job is a command line tool by Google called woff2.
@supports
Modern browsers only download a font when it is needed – that is when it is used in a CSS selector that matches a node connected to the DOM. That means it is possible to use @supports
to only download the font in supporting browsers.
Axes
These are the default or “registred” axes. Just remember that not all fonts will use all axes. Even if an axis is defined, the values defined within the font might only be part of the span of possible values.
wght corresponding to font-weight
. Value is anything between 1 to 999. Can also use keywords:
- thin or hairline (100)
- extra light or ultra light (200)
- light (300)
- normal (400)
- medium (500)
- semi bold or demi bold (600)
- bold (700)
- extra bold or ultra bold (800)
- black or heavy (900)
- inherit / initial / unset
wdth corresponding to font-stretch
. Value is anything between 50% to 200%. Can also use the keywords:
- ultra-condensed (50%)
- extra-condensed (62.5%)
- condensed (75%)
- semi-condensed (87.5%)
- normal (100%)
- semi-expanded (112.5%)
- expanded (125%)
- extra-expanded (150%)
- ultra-expanded (200%)
- inherit / initial / unset
ital corresponding to font-style: italic
. Value is from oblique -90deg to oblique 90deg.
slnt corresponding to font-style: oblique
. Values between -90deg and 90deg with a default to 14deg.
opsz corresponding to font-optical-sizing
. Set to auto or none. The initial value is auto, which means it is active by default if the axis exists on the variable font in use.
Italic vs. Oblique
The difference between an italic and an oblique font is that the italic version of a font is both angled and has a slightly tweaked glyph design. The oblique version is angled and adjusted as such, but otherwise, there is no difference to the roman (normal and upright) version of the font.
Font-optical-sizing
Font-optical-sizing is size-specific optimizations to improve a font’s readability. It is used to adjust the font depending on the environment where it is being used. For example, a font can be programmed to add embellishments when viewed on larger screens, to remove fine details on smaller text, or to increase x-height (the height of lower case letters, aligned with the height of the letter “x”) in certain situations to improve readability.
Variable fonts with this axis implemented, therefore, makes websites more accessible.
Custom Axes
Font designers can create custom axes, giving them a name consisting of any 4 letters. Custom axes are used to control any other aspect of a font that the designer wishes to be able to gradually alter.
Adding a Variable Font to a Web Page
Adding a variable font to a web page is done with @font-face. The file format is set to the file type. In previous implementations, a suffix “-variations” was used, but now it does not seem to be needed.
@font-face{
font-family: "variableFont";
src: url("variableFont.woff2") format("woff2");
}
Font-variation-settings
To control the axes and set font variations, it is possible to use either the CSS property font-variation-settings
, or the properties font-weight
, font-stretch
, font-style
and font-optical-sizing
separately.
According to the spec, the preferred way is to use the properties for each style separately. Reason being that font-variation-setting
is meant to be used for custom axes. If you run into browser compatibility problems, font-variation-settings
is rumoured to be more stable across browsers.
No matter which syntax you use, you need to find out which axes are supported in the variable font, and between which values they range. Unless this is specified in any documentation that you can find about the font, this information should be found in the font variation (fvar) tables in the font files.
The easiest way of extracting this information is to drop the font into the wakamaifondue.com and hope the info you need will be revealed. If that is not the case, you might need to use a tool like FontView in combination with Fonttools as described more in-depth in this article.
Add Axis Range
Specify the range for the axis you wish to use. Otherwise, the property might use a default fallback that risk hindering usage of the variable font. In the future font-weight
will, for example, get a default fallback of auto, meaning the range might not be needed.
@font-face{
font-family: "variableFont";
src: url("variableFont.woff2") format("woff2");
font-weight: 1 999;
}
Fallbacks
Add the non-variable font or fonts using @font-face
as usual.
/*Fallback fonts*/
@font-face {
font-family: "fallbackFont";
src: url("fallbackFont-regular.woff2") format("woff2"),
url("fallbackFont-regular.woff") format("woff");
font-weight: 400;
}
@font-face {
font-family: "fallbackFont";
src: url("fallbackFont-bold.woff2") format("woff2"),
url("fallbackFont-bold.woff") format("woff");
font-weight: 700;
}
Add the @supports
rule. If you experience inconsistent weight behavior in different browsers, try adding the default weights you want each font to use. (Advice from “How to use variable fonts in the real world”.)
html {
font-family: "fallbackFont", sans-serif;
font-weight: 400; /*if inconsistent weight behavior*/
}
strong, b {
font-weight: 700;
}
@supports (font-variation-settings: normal) {
html {
font-family: "variableFont", sans-serif;
font-weight: 400;
/*if you run into browser compatability problems,
try the syntax:
font-variation-settings: "wght" 400; */
}
strong, b {
font-weight: 625;
}
}
Future syntax
In the future, the syntax would change to make it possible to incorporate checking for browser support in the format()
part. That would make it possible to use variable fonts outside of @supports
rules, and still have a fallback solution in place.
/*Future syntax*/
@font-face {
font-family: "futureVariableFont";
src: url("fallbackFont.woff2") format("woff2"),
url("fallbackFont.woff") format("woff");
src: url("futureVariableFont.woff2") format("woff2" supports variations);
}
Word of Advice
Since the specs might change and the technology is ever evolving, testing is key to make sure the font displays and behaves as expected in the browsers and browser versions most important to you.
There might still be undiscovered quirks and edge cases that need to be worked around. If you come across one of those, please share your experiences and solutions with the community. That is what makes it possible for all to keep up with the rapid changes of the web world.