Draft: started •
1. Never assume that a named font will work
There are no web-safe fonts; none are available across all major platforms.
Web fonts (@font-face and all) are not safe either:
- If not inlined, subresources can fail to load for all kinds of network reasons.
- Font loading is an area of concern for security, so some block it for safety.
- uBlock Origin has a dedicated button for disabling remote fonts.
- I think some browsers’ data-saving modes block fonts from loading.
(And those that don’t, should.)
Or the user might have elected not to let websites choose their own fonts.
I’ve been doing that since 2020, and it makes the web so much better.
For me, generic families are the only ones that will work.
One related JS thing: if you ever use document.fonts.load("1em my-web-font"),
remember that it’s fallible: the promise it returns may be rejected.
I came across about four things in the six years 2020–2025 that broke for this reason
(and two of them were in 2025).
Now for a couple of consequence of this. I see this forgotten occasionally, since its lack doesn’t affect most people. As a concrete example, at the time of writing, Adel Faure’s ASCII might fly? artwork a) Always include
monospace if you want the text monospaced
Sometimes on pages that were all-monospace for no good reason.
Those times, it honestly made the pages better! But other times it damages things.
is missing monospace, and looks a little like this for me:
(assuming your styles or user agent don’t make it monospaced!) . . . .
_.---._ . . . . . .
. . . '-. . . . . . . . . . . . .
:.:.:.:.:.\. . . . . __ . . . . . .
:.:.:.:.:.:'-.------------_.-'..'-.-----------------------
_:.:.:.:.:.:.:\--._____.-'.:.:.:.:.\-.__::::::::::::::::::
.'-.::.::.::.::'-._'-._____::..:.:.:.:'-:-.-..._:.__:.:.:.
-.-.\::.:::.::::::::::__::::(._____:.::.:::.::::'-.:=-.. .
.-.-.'--.___:.::::.:::::::( '.--._''':.::::::::::::____.-
-. -.'---.::::::::::'-. )::::::::::::_.-----'.-.-.-
.^.-.-.-.-.-.-. \:::::::____TT_____.______'-.-.::.::.-._.
/ \::.:^:.:______.^-----/_-_ -_/\-.-/__/\__\::^:.^::.-..::
/ \ / \_/-_-_- /\\___/__/\/_/ \__|LL LL|-/ \/ \( ).^
._\..____/______/LL\___|LL__LL| /___/\ LL|_______( ^ /
)__/____|LL LL|LL|L L|LL||LL| |L L||--___/\______\./ \.
/\__|____|LL__LL|_________===_______---/\___\LL__LL| / \ ^
||/\-_-_-\LL||L/____/____/\ /-_-_- /\\ ||______||LL|:/_\/
:/__\_____\___=|L L |L L ||/______/LL\ /_-_-_-/\ .::::|'/
-||||L L/____/\__==_______-|LL||LL| |/______/ \i-i-i-i/_
7 - - --|L /\____\/\-_-_-_\==_""--""= |LL__LL| |: : : :L|
pre {
font-family: "jgs", monospace;
}
I was actually going to write that last point as “always include a generic family”, Although Otherwise, it’ll use the default font, which is probably serif but could be something else altogether.
but really it’s only monospace that it’s important for. Still— b) Include
serif or sans-serif if you want that kind of fallback fontserif or sans-serif are rarely important,
you probably want to include one of them all the same. font-family: Arial, sans-serif;font-family: Times New Roman, serif;
2. Stop enumerating fonts that the system might have installed
I’ve seen too much of this kind of thing:
font-family: "Arial", Helvetica, 'Helvetica Neue', Liberation Sans, "Noto Sans", sans-serif; Google Sans, Roboto, Arial, sans-serif Definitely ditch Arial: it’s never going to be better than sans-serif. Also ditch Roboto: it’s almost never . It doesn’t help. sans-serif will resolve to a font no worse than those you named, and quite possibly better.
Here’s a real example I just came across (with spaces restored after punctuation, for it was minified):
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif This is ridiculous, strictly worse than font-family: monospace, monospace. monospace will resolve to a font that is no worse.
Now I’m not saying there’s never a case for it. This is an exception Consider Georgia and Times New Roman, both serifs from Microsoft’s Core fonts for the Web.
Consider Georgia and Times New Roman, both serifs from Microsoft’s Core fonts for the Web.
But they have quite different character: Georgia is a good deal wider.
If that’s what you want for stylistic reasons, I will not begrudge you font-family: Georgia, serif. a) Have at most one named, non-web font
But they have quite different character: Georgia is a good deal wider.
If that’s what you want for stylistic reasons, I will not begrudge you font-family: Georgia, serif.
3. Strongly consider using only a generic family
So perhaps we’ve removed the locally-installed fonts as not useful;
now how about web fonts?
A web font is slower than no web font; and you can run into issues loading them; so we got font-display.
But really, instead of messing around with block and swap periods and redrawing and reflowing tradeoffs,
why not just use whatever font the user has?
It won’t be that bad. They might even have chosen fonts themselves.
Consider it. Historically, This is mostly Microsoft’s fault for using that abomination Courier New, Then, Apple introduced Menlo, and people liked it, Well, those days have passed. Browser defaults are all better now. So drop the Here’s a real declaration I just came across (with spaces added after punctuation; it was minified): If you ever deliberately put Ugly bit of browser history which doesn’t seem to be documented in any spec I can find, If you use If there’s a second family in the list, this doesn’t happen; Or set the font-size manually, if you prefer. If you’re using Lightning CSS, it will ruin This only affects I’d like to see if we can convince browser-makers to abandon the a) Yes, even for monospace
monospace defaults were bad.
which was digitised badly and is effectively a 200–250 weight instead of a 400.
so people started putting that in their font stacks,
since the browser makers weren’t updating monospace.
And so it went on.
They may not yet be spectacular in all cases, but they’re never bad any more. Menlo, Monaco, Consolas, Bitstream Vera Sans Mono, Courier, Courier New, and try just leaving monospace. font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serifCourier New in a font stack, I’m not sure if we can be friends. b) Actually, write
monospace, monospace
but everyone that old remembers. font-family: monospace; (explicitly or implicitly), font-size will probably default to 81.25% instead of 100%.
(Users can change the generic fonts, the base font size, and the base monospace font size.)
so font-family: my-web-font, monospace; is fine,
and font-family: monospace, monospace; is fine. monospace, monospace;
so for my part I’m writing monospace, m for now. monospace. And maybe text that changes the language, but that’s different again. monospace size thing,
and increase it from the probably-13px to probably-16px.
I guess CSSWG would be the venue to suggest it.
4. Don’t use system-ui or ui-* for content
UI fonts are designed for short UI texts, not longform content.
UI fonts may not support your content language well: macOS is good about it,
but Windows is not, and you’ll end up with things like CJK users getting a bad monospaced font.
Sometimes, people have even deliberately chosen ridiculous system UI font—
quite common in some Android circles.
I presume system-ui will make content look ridiculous too.
w3c/csswg-drafts issue #3658 discusses some of the problems,
concluding that system-ui has been extensively abused.
mdn/content issue #41244 finally added a note to MDN discouraging its overuse.
These families have largely been used as a proxy for better default fonts. This is not a good use of them.
I believe system-ui was a mistake.
They should have left it at -apple-system and had BlinkMacSystemFont change to that:
no other platform had a useful equivalent concept at the time (though some do now),
and it was evident from well before the time of standardisation that
almost all use of this stuff was abuse working around the fact that
browsers weren’t updating their poorly-considered, ancient defaults for the existing generic families.
I believe that ui-serif, ui-sans-serif, ui-monospace and especially ui-rounded was an entirely stupid idea which should still be ripped out.
Especially given that they’re not expected to map to any font on… anything non-Apple.
Being Apple-only, they don’t need to be in the spec.
They can just expose them as fonts with names that just happen to start with -apple-.
(What, we’re not doing prefixes any more? This isn’t a prefix, just looks like one.)