How to set font family but retain fallback stack?

Viewed 241

Is it possible to easily set a custom local font using JavaScript, but retain some default font-family stack in case the user tries to set a font that doesn't exist?

E.g., if the stack is font-family: Courier, monospace;, how to add to the beginning of the stack without resorting to manipulating strings?

1 Answers

Method 1: CSS custom properties

The original answer below (method 2) had some issues, but then I came up with a more straightforward solution using CSS custom properties (variables).

p {
    font-family: var(--userfont), Courier, monospace;
}
document.documentElement.style.setProperty('--userfont', 'Arial');
// Result is equivalent to font-family: Arial, Courier, monospace;

document.documentElement.style.setProperty('--userfont', 'non existant');
// Result is equivalent to font-family: 'non existant', Courier, monospace;
// which falls back to Courier assuming 'non existant' isn't actually the name of
// an installed font

JSFiddle demo

Support

Check here

Unlike method 2 below, this method is supported by Edge v15+. Also it avoids the bug in older versions of Chromium that method 2 suffers from.


Method 2: FontFace

You can use @font-face, or rather the JavaScript API FontFace.

p {
  font-family: userfont, Courier, monospace;
}
function setUserFont(fontName) {
    const userFontFace = new FontFace('userfont', `local(${fontName})`);
    document.fonts.add(userFontFace);
}

setUserFont('Arial');

JSFiddle demo

Support

Check here

Old/non-Chromium Edge (up to v18) does not support the JavaScript API.

It appears there is a bug in Chromium 73 whereby fonts such as "Segoe UI Light" will not be found, only the base "Segoe UI" will be found. This applies to @font-face as well. It seems to be fixed as of Chrome 80.

Related