Substitute web fonts with StopTheMadness, Part 2

November 5, 2022
By Jeff Johnson of Underpass App Company

Part 1 explained how to substitute fonts on the web with StopTheMadness using @font-face rules in a custom <style> element. Here's an example of a rule that substitutes Helvetica for Arial.

@font-face {
 font-family: "Arial";
 font-stretch: 50% 200%;
 font-style: normal;
 font-weight: 1 1000;
 src: local("Helvetica");

Part 2 will explain a couple of inherent limitations to this substitution. The first limitation is that Safari refuses to display user-installed local fonts. The only local fonts allowed are system fonts. This limitation is caused by tracking prevention in WebKit.

Changed font availability to web content to only include web fonts and fonts that come with the operating system, but not locally user-installed fonts. Web fonts and the common set of web-safe fonts, as well as other OS-bundled fonts, are still available.

The list of fonts installed on your computer could be used to "fingerprint" you by websites, which is why Safari is limited to system fonts that everyone has installed. I'm not aware of any way to get around this limitation. Unfortunately, there doesn't appear to be a hidden preference to enable user-installed fonts in Safari.

The second limitation is that the font-family must specify a family name such as "Times" or "Helvetica". It doesn't work to use a generic name like serif, sans-serif, monospace, system-ui, or -apple-system.

Safari, Google Chrome, and Firefox all use Times when no font is specified. They also use Times for the serif font. For sans-serif they use Helvetica. For monospace, Safari and Firefox use Menlo, while Chrome uses Courier. So you can override the fonts by name: "Times", "Helvetica", "Menlo", and "Courier".

In Safari there's a little trick: even though you can't use serif, sans-serif, or monospace to specify the font-family in the @font-face rule, you can use -webkit-serif, -webkit-sans-serif, and -webkit-monospace. These aren't "generic" names; they represent the actual fonts used by WebKit, which is why they work when the generic names don't.