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.