Get affordable and hassle-free WordPress hosting plans with Cloudways — start your free trial today.
The @font-feature-values
at-rule gives a human-readable name to the font’s settings declared in the font-feature-settings
property, such as style sets, ornaments, and swashes. Since similar feature settings vary from font to font, @font-feature-values
groups them under a common name. This new name can then be applied with the font-variant-alternates
property.
/* Define the feature values with a name */
@font-feature-values Noble Company {
@stylistic {
curly: 1; /* Sets salt 1 on */
}
}
h1 {
font-family: Noble Company;
font-variant-alternates: stylistic(curly); /* Apply the features */
}
The @font-feature-values
at-rule is defined in the CSS Fonts Module Level 4 specification.
Syntax
@font-feature-values = @font-feature-values <family-name># { <declaration-rule-list> }
@historical-forms = @historical-forms { <declaration-list> }
@stylistic = @stylistic { <declaration-list> }
@styleset = @styleset { <declaration-list> }
@character-variant = @character-variant { <declaration-list> }
@swash = @swash { <declaration-list> }
@ornaments = @ornaments { <declaration-list> }
@annotation = @annotation { <declaration-list> }
Arguments, rules and descriptors
<family-name>
: This is the font family the font features apply to.@stylistic
: This sets the index for stylistic alternates, which match the OpenTypesalt
feature tag.@styleset
: This sets the index for stylistic sets, which match the OpenTypess01
toss20
feature tag.@character-variant
: This sets the index of specific character variants, which match OpenTypecv01
tocv99
feature tag.@swash
: This sets the index of swash glyphs, which match the OpenTypeswsh
feature tag.@ornaments
: This sets the index of default glyphs with ornaments, which match the OpenTypeornm
feature tag.@annotation
: This sets the index of alternate annotation forms, which match the OpenTypenalt
feature tag.
While a @historical-forms
rule exists, its usage is redundant since font-variant-alternates
takes a historical-forms
keyword, not a function.
@font-feature-values
?
Why To understand why we need @font-feature-values
we talk about what a font feature is and how they workk with the font-feature-settings
property.
You may have heard about the OpenType format and how it’s considered the uppermost font format. On the web, we use them all the time, mainly as .woff
and .woff2
files, which work as compressed wrappers for OpenType (and TrueType) fonts.
But why is OpenType considered so good? It has many technical improvements from past formats. Still, from a web design perspective, it allows font designers to save different glyphs of the same character for different situations, which can then be picked by the web designer/developer. For example, the same OpenType font could have alternate glyphs for the letter “A”.

This is just one of many examples; an OpenType font could have alternates for kerning, ligatures, swashes, and many other variants that can be picked by the font user. These variations on the same font are called font features.
In CSS, there are many ways to enable a font feature. First, common font features have their own font properties. For example, the font’s kerning and ligatures can be enabled through the font-kerning
and font-variant-ligatures
properties. But this isn’t true for most features, so we have to enable them through the font-feature-settings
property.
The font-feature-settings
property takes a list of tuples, each made of the font feature we want to enable and an index. The font feature is written as a four-letter string, while the index is just an integer that turns on the feature.
.element {
font-feature-settings: "kern" 0, "swsh" 1;
/* Sets kerning off and swashes on */
}
Some features can simply be turned on and off, in which case the 0
index disables them and 1
enables them. However, some fonts can have more than one state, for example, instead of enabling all swashes, the "swsh" 1
could enable the swash for a group of characters, "swsh" 2
another group, and so on.
This leads us to the most important concept: font features aren’t standard! So what "swsh 1"
means may change from font to font; it could even do nothing in some fonts, which is why font-feature-settings
is generally discouraged. You don’t always know which features a font file supports and need to use a tool like Wakamai Fondue to expose them.
Here is where @font-feature-values
comes in. For a specific font, the at-rule assigns a human-readable name to a set of font features. You can then think of @font-feature-values
as a shortcut for font-feature-settings
. We can have several @font-feature-values
for different fonts under the same name, and this way, if the font-family
changes, then the browser will pick the correct @font-feature-values
for that font.
For a detailed explanation of each font feature accessible through @font-feature-values
, check the font-variant-alternates
property.
Basic usage
First, we will need an OpenType font with some font features to play with. I’ll be using The Melody by Riza Haitami. We can know exactly which features it supports using the Wakamai Fondue tool, which returns us the following features:

If we inspect further, we’ll see it has a salt
(Stylistic Alternates) available feature, which is turned off by default.

However, just setting salt 1
through font-feature-settings
doesn’t give us a lot of information on what we are exactly doing to the font. Instead, we can use @font-feature-values
and give it a name. In this case, the salt
feature appears to give the characters a decorative tail, so I am going to name this set of features tails
. We name it with the @stylistic
rule, which is in charge of setting the index for salt
features.
@font-feature-values Melody {
@stylistic {
tails: 1; /* Sets salt to 1, which enables it */
}
}
And to apply it to an element, we will use the font-variant-alternates
property. It takes a function with the same name as the rule we used (stylistic()
in this specific example) and the feature name as an argument (tails
in this example).
h1 {
font-family: Melody;
font-variant-alternates: stylistic(tails);
}
The @font-feature-values
at-rule shines when we have several fonts with similar font features but under different indexes. For example, both the Andior by Yudi Pratama Chandra and Denhils by Burhan Afif fonts have a font feature that enables “tails”. However, Andior has the feature listed under ss03
, while Denhils has it under ss04
:


So, if we used font-feature-settings
to enable the feature for an element, it would mess up the text if the font-family
changes from one another. Using @font-feature-values
, we can set the correct feature index under the same tails
name. This time using the @styleset
at-rule which sets the index for ssXX
features:
@font-feature-values Andior {
@styleset {
tails: 3; /* Enables ss03 */
}
}
@font-feature-values Denhils {
@styleset {
tails: 4; /* Enables ss04 */
}
}
Then the browser will enable the correct feature based on the font-family
:
.andior {
font-family: "Andior";
font-variant-alternates: styleset(tails);
}
.denhils {
font-family: "Denhils";
font-variant-alternates: styleset(tails);
}
We could also have several features defined on the same rule:
@font-feature-values Skrine {
@styleset {
backtail: 1; /* sets ss01 on */
fronttail: 2; /* sets ss02 on */
pigtail: 3; /* sets ss03 on */
fancy: 6; /* sets ss06 on */
}
}
Specification
The @font-feature-values
at-rule is defined in the CSS Fonts Module Level 4 specification, which is currently in Editor’s Draft.
Browser support
Both the/ and the font-variant-alternates
are supported on all browsers.
More information
- Wakamai Fondue (Roel Nieskens)
- The Complete CSS Demo for OpenType Features (Sparanoid)