Puttin' the eek back in geek

Boiled down: fixing the variable font inheritance problem

September 7, 2022

Both font-feature-settings and font-variation-settings take a list of font properties. The caveat is that every property you don’t set will be set to it’s default value. This makes it hard to change one setting without unsetting the rest. But luckily CSS variables can be used to fix this problem!

In the following example the weight will be set to 100 and the width to 50%, resulting in “Hello world” being rendered in a narrow bold style:

<style>
.a {
    font-variation-settings: "wdth" 50, "wght" 700;
}
</style>

<div class="a">
    Hello world
</div>

But in this case “Hello world” will be rendered in a narrow regular style:

<style>
.a {
    font-variation-settings: "wght" 700;
}
.b {
    font-variation-settings: "wdth" 50;
}
</style>

<div class="a">
    <div class="b">
        Hello world
    </div>
</div>

The reason is that class b will overwrite everything set in class a. The browser doesn’t say “the weight was set to 700 earlier, so I’ll just inherit that”. It says, “weight is not set, so I’ll use the default value of 400”.

To prevent this you can use CSS variables to keep track of each value, as they will cascade down nicely:

<style>
.a, .b {
    /* Default values */
    --wght: 400;
    --wdth: 100;
    font-variation-settings:
        "wght" var(--wght),
        "wdth" var(--wdth);
}
.a {
    /* Override just the "wght" */
    --wght: 700;
}
.b {
    /* Overwrite just the "wdth" */
    --wdth: 50;
}
</style>

<div class="a">
    <div class="b">
        Hello world
    </div>
</div>

Now “Hello world” will be rendered in a narrow bold style, like you’d expect. Every change in a CSS variable’s value will trickle down and be used whenever font-variation-settings gets applied.

Note that you normally don’t need to use font-feature-settings or font-variation-settings. In our example you should use font-weight and font-stretch instead of manipulating the axes directly. Most OpenType features can be set through font-variant. If you do need access to low level features (for animations, specimen sites, custom axes, etc.), using CSS variables is a good way to fix the inheritance problem.

There's also a more verbose and beginner-friendly version of this article: Boiling eggs and fixing the variable font inheritance problem.