Skip to main content
Dublin Library

The Publishing Project

Calculating font overrides


As a follow-up to the prior post on converting JSON/JSON5 to CSS, we will look at providing font override metrics for fallback fonts and how to use them.

Katie Hempenius provides a spreadsheet with the override values for all fonts in the Google Fonts collection.

If the font is not available in Google Fonts or you have the font available, you can use tools like Fontkit to query the font and get metrics for font fallbacks.

The metrics that we need are:

  • ascent
  • descent
  • lineGap
  • UnitsPerEm

And we use them to calculate the override values as follows:

  • ascent-override = ascent/unitsPerEm
  • descent-override = descent/unitsPerEm
  • line-gap-override = line-gap/unitsPerEm

The rest of the post will look at one way of generating these metrics and how to use them.

The following block of text does the following:

  1. Opens a font with FontKit
  2. calculates each override metric and assigns it to a variable that we can later push into an array
function getFontMetrics(font) {
  const myFont = fontkit.openSync(font);

  let ascentOverride = `${myFont.ascent / myFont.unitsPerEm}`;
  let descentOverride = `${myFont.descent / myFont.unitsPerEm}`;
  let lineGapOverride = `${myFont.lineGap / myFont.unitsPerEm}`;

This function will produce the values that we need to define overrides in the fallback font.

When running the code with Recursive we get the following values:

  • Ascent override: 0.95
  • Descent override: -0.25
  • Line-gap override: 0

Now we can create the fallback @font-face declarations.

The next example defines two fallback fonts, Arial and Roboto, with overrides based on Recursive, our primary font.

Note how we define local sources for the fonts using local plus the font name.

We then define the font stack in the body element.

@font-face {
  font-family: "Fallback1";
  src: local("Arial");
  ascent-override: 95%;
  descent-override: -25%;
  line-gap-override: 0;

@font-face {
  font-family: "Fallback2";
  src: local("Roboto");
  ascent-override: 95%;
  descent-override: -25%;
  line-gap-override: 0;

body {
  font-family: "Recursive", "Fallback1", "Fallback2";

This is the first reduction of layout shift caused by font substitutions.

One thing I'm curious about is whether the system fonts stack may help reduce the shift further.

Edit on Github