EJS logo

This site’s type is now variable

I’ve been writing and editing a lot of content about variable fonts for Google Fonts Knowledge recently, so I figured it was high time my own website switched over to use the variable version of Ohno’s Degular. And now it’s live — you’re reading text set in it right now. Lucky you.

Now, I’ll add that I’m a variable font realist. That is: I’m not particularly excited about adjusting a heading’s weight from 900 to 901 — the bigger integers work just fine for most of my needs, at least on this site, and the more exciting stuff, in my opinion, is being able to more smoothly transition from a Text optical size to a Display optical size via everything in between. The optical sizes of Degular’s static version are wonderful: at the smallest end, the Text size has less contrast, a larger x-height, and more generous spacing; at the other end, Degular Display is bursting with details and gets super tight. Degular (the, er, normal version) sits in between the two. But these jumps are jarring, because the difference between each optical size is not exactly subtle, so being able to move between them with the subtlety of the opsz axis has been really nice.

So, having convinced myself that it was finally time to get off my arse and do this, I thought I’d document the process for anyone else thinking of doing the same—especially as I made some dumb mistakes along the way! And I’ve also written a more general guide on switching from static fonts to variable fonts for GFK, which’ll be published in the near future.

The first thing I did was lose almost everything in my CSS file for @font-face declarations. (At this point, I forgot to kill a font-weight: 400; declaration, which later gave me a lot of grief. More on that in a sec.)

@font-face {
  font-family: 'Degular Variable';
  font-style: normal;
  font-display: fallback;
  src: url(/path/to/DegularVariable.ttf) format('truetype');
}

With the fonts loaded, it’s onto styling. Another primer for you (and me, given my terrible memory): “Styling type on the web with variable fonts” is on GFK. Thanks, past self!

The first little hurdle I encountered was that all of my type was slanted. I’m not sure why this was the default, but there you go. Got to turn it off:

body {
    font-variation-settings: 'slnt' 0;
}

After that, I was eager to jump into all the optical sizing goodness. The fact that automatic optical sizing is well supported in modern browsers is great, but I wanted to have my own control over that, so the first thing I did was turn that off, too:

font-optical-sizing: none;

Now onto some fairly basic manipulation of this axis, and as I needed to change this value depending on the viewport width, I obviously needed media queries. I’m nesting them because I’m using SASS to make life easier. (Maybe we don’t need SASS anymore? I don’t know. I’m an old guy now. Give an old guy a break.)

body {
  font-optical-sizing: none;
  font-variation-settings: 'slnt' 0;
  font-variation-settings: 'opsz' 100;

  @media screen and (min-width:42em) {
    font-variation-settings: 'opsz' 150;
  }

  /* etc. */

}

But hang on. At this point, something went horribly wrong. My slanted text was back! Why? Because of the variable font inheritance problem outlined by Roel Nieskens, that’s why! So easy to forget all this stuff, right?

The solution, as Roel says, is to use a CSS custom property (also known as a CSS variable, but yes, that name is confusing in the contexts of VFs). I set up and named my custom properties like this, right at the top of my main typography stylesheet:

* {
  font-variation-settings:  'opsz' var(--vf-opsz), 
                            'slnt' var(--vf-slnt), 
                            'wght' var(--vf-wght);
}

Then it was a case of reformatting my existing CSS to use these custom properties:

body {
  font-optical-sizing: none;
  --vf-opsz: 100; /* Optical size: 0–1000 */
  --vf-slnt: 0; /* Slant: 0–10 */
  --vf-wght: 100; /* Weight: 0–1000 */

  @media screen and (min-width:42em) {
    --vf-opsz: 150;
  }

  /* etc. */

}

From this point, it was mainly a case of going through all of the styles for the different elements, tweaking Degular’s opsz, slnt, and wght axes via the custom properties, and throwing in some nested media queries whenever I needed a value to change for a different viewport width. To be honest, I’m still finessing this — I haven’t yet achieved some of the more subtle changes I wanted to make with these variable axes at my disposal. But now that everything’s set up, it’s going to be easy to add in a few extra media queries as and when.

Oh, and I mentioned that troublesome font-weight: 400; declaration, didn’t I? Well, I’d accidentally left it in when I switched from the static variation and hadn’t noticed anything amiss, so it went undetected. But when I viewed the site on iOS, the type looked awful. Weird faux-bolding going on, and almost faux width adjustment, too, which started widening the vertical strokes of the letterforms. Urgh! Chris suggested it could be the browser synthesising weight for some reason, and it was! Adding font-synthesis: none; solved the issue. But then when Laurence very kindly looked into it some more, he discovered that left-over font-weight: 400; declaration and realised it was causing the browser to only load the 400 weight and then synthesise every other value used on the wght axis. Yikes! A schoolboy error on my part, although in my defence, only the mobile browsers tripped up on this, which is why it was hard to find. Anyway, I’ve suffered so now you don’t have to. And my shame is forever documented on Twitter.

Feel free to peek under the hood if you’re interested, and keep your eyes out for that forthcoming article on Google Fonts Knowledge. Oh, and I made a few general typographic tweaks throughout the site, too. Please let me know if you spot anything that doesn’t look right.