Tom MacWright

On font fallbacks and failures

A few thoughts I’ve had about typography on the web:

Monospace fonts are only as monospace as their character support

I was recently using Monodraw to add illustrations to some code comments, explaining, in this case, how a CSS flexbox layout worked. I drew the graphics, chose UTF8 mode, copied & pasted into neovim, and they looked great. I pushed the commit, reviewed it on GitHub, and what I saw were misaligned shapes, everywhere. I considered it for a while, checking that Monodraw didn’t have any widely-reported bugs. Checked in the web inspector that GitHub was showing the correct content.

Then I realized: what is monospace? In this case, monospace is a property of a font, not text. You don’t write in your CSS stylesheet font-type: monospace, you just specify a monospace font, like font-family: Menlo, monospace. Your browser doesn’t know whether you intend for all that output to be monospaced or not, only that you chose a certain font and that font happened to have all characters with the same width-to-height ratio, and constant kerning.

GitHub, to their credit, use something similar to the system font stack: a set of good-looking fonts that are on people’s computers. But nonetheless, the font first in their font stack that was present on my computer – Consolas – didn’t have some of the characters that Monodraw uses in its output. So the browser fell back to a font that did have those characters (I think Menlo), but had a different ratio of width to height, so the lines that included ‘exotic’ characters were misaligned.

Conceptualizing typography choice

Working with maps made me think of fonts in a different way. When we’re designing websites and other material, we write most of the content and choose how that content is displayed. You can seek a certain harmony here, choosing modes of display that fit the text.

But there are known unknowns: contributed and existing content. For maps, that’s the names of places around the world, in their native characters. The norm for web maps is global coverage, so every map you design with the viewport comfortably centered over some major American city with place names mostly in the ASCII range can be panned over to China, with its hundreds of glyphs, or Japan, with its multiple scripts.

For other websites - like for the ones I’m working on now - the wildcard is user generated data. The hope is that it’ll be successful enough that people around the world will use the website. Their names will have a wide range of characters, like æ and ㄞ, and the content they author will too.

Not to pick on webfonts too much, because system fonts even are limiting in this way - the system default version of Futura, for instance, only has 439 glyphs and support for a small subset of the world’s languages.

A webfont with wide Unicode coverage will have poor load performance because it includes so many glyphs, and an efficient font with fewer glyphs will have weaker international support. The way forward is unicode range subsetting, a technique I wish was more common and much more developer-friendly.

Debugging fonts should be better

I want more robust tools for inspecting fonts. I love Chrome’s Web Developer tools, but they offer little in the way of inspecting fonts. macOS’s default management tool, Font Book, also doesn’t offer much in terms of browsing - searching for, say “a font that includes tabular numbers” isn’t supported, as far as I can tell.

Fonts on the web as currently designed – and fonts in general – break quietly, which in my opinion is a real issue. They’ll quietly synthesize a shameful faux bold version if a true bold isn’t available. When a glyph isn’t available, they’ll search down the font stack and substitute a usable-but-not-quite-right replacement.

In production, this is desired behavior. We prefer imperfect visual quality to complete breakage. But in development, it’s a frustrating mess. Faux bolds and fallback glyphs are, in many cases, error states, or they at least deserve a warning. The proposed font-synthesis property will turn off faux bold generation, but without any feedback: if you request a bold variant and one doesn’t exist, it simply shows the existing font.

For now, I’m going to experiment with adding a debugging font stack that only includes my first-choice font and then an obnoxious and obvious fallback font to make errors louder.