font-family 推荐
摘要
一篇详细的博客文章,认为没有哪种字体真正是网页安全的,并建议总是在CSS font-family声明中包含通用字体族,如monospace、serif或sans-serif。它批评了过度的字体堆叠,并建议信任系统的默认字体选择。
<p><a href="https://lobste.rs/s/madoeq/font_family_recommendations">评论</a></p>
查看缓存全文
缓存时间: 2026/06/25 15:13
# font-family 推荐 — Chris Morgan
来源:https://chrismorgan.info/font-family
草稿:开始于2026-05-09 • 标记为/css (https://chrismorgan.info/css)、/opinions (https://chrismorgan.info/opinions)
## 1. *永远不要*认为指定的字体一定会生效
没有所谓的网页安全字体;没有任何一种字体在所有主流平台上都能使用。
Web 字体(包括 `@font-face` 等)同样不安全:
- 如果未内联,子资源可能因各种网络原因加载失败。
- 字体加载涉及安全问题,因此有些用户会出于安全考虑阻止它。
- uBlock Origin 专门有一个按钮用于禁用远程字体。
- 我认为某些浏览器的省流量模式会阻止字体加载。(那些没这么做的浏览器,*应该*也这么做。)
或者用户可能选择不让网站自行决定字体。
我从 2020 年起就这么做了,这让网页体验*好了很多*。
对我来说,通用字体系列是*唯一*能保证生效的。
一个相关的 JS 注意点:如果你使用了 `document.fonts.load("1em my-web-font")`,*记住它可能会失败*:它返回的 Promise 可能会被拒绝。在 2020–2025 这六年里,我遇到了大约四起因此而导致的问题(其中两起发生在 2025 年)。
接下来说说由此带来的几个推论。
### a) 如果希望文本等宽,*务必*包含 `monospace`
我偶尔会看到有人忘记这一点,因为缺少它并不会影响大多数人。有时出现在整个页面都在用等宽字体但毫无道理的情况下。说实话,那种情况下,缺少它反而让页面更好看了!但其他时候,它会造成损害。
比如,在撰写本文时,Adel Faure 的作品 *ASCII might fly?* (https://adelfaure.net/artware/ascii_might_fly/) 缺少 `monospace`,在我这里看起来有点像这样:(前提是你的样式或用户代理没有强制使用等宽字体!)
``
. . . .
_.---._ . . . . . .
. . . '-. . . . . . . . . . . . .
:.:.:.:.:.\. . . . . __ . . . . . .
:.:.:.:.:.:'-.------------_.-'..'-.-----------------------
_:.:.:.:.:.:.:\--._____.-'.:.:.:.:.\-.__::::::::::::::::::
.'-.::.::.::.::'-._'-._____::..:.:.:.:'-:-.-..._:.__:.:.:.
-.-.\::.:::.::::::::::__::::(._____:.::.:::.::::'-.:=-.. .
.-.-.'--.___:.::::.:::::::( '.--._''':.::::::::::::____.-
-. -.'---.::::::::::'-. )::::::::::::_.-----'.-.-.-
.^.-.-.-.-.-.-. \:::::::____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|
``
加入后备字体 `monospace`:
``
pre {
font-family: "jgs", monospace;
}
``
其实我本来想写“始终包含一个通用字体系列”,但真正*重要*的只有 `monospace`。不过——
### b) 如果你想要衬线或无衬线的后备字体,请包含 `serif` 或 `sans-serif`
虽然 `serif` 或 `sans-serif` 很少*至关重要*,但你很可能还是应该包含其中一个。
``
font-family: Arial, sans-serif;
``
``
font-family: Times New Roman, serif;
``
否则,它会使用默认字体,这个字体*可能*是衬线字体,但也可能是完全不同的东西。
## 2. 不要再列举系统可能已安装的字体了
我见过太多这样的写法:
``
font-family: "Arial", Helvetica, 'Helvetica Neue', Liberation Sans, "Noto Sans", sans-serif;
``
``
Google Sans, Roboto, Arial, sans-serif
``
*绝对*要丢弃 Arial:它永远不会比 `sans-serif` 更好。也要丢弃 Roboto:它几乎从不更好。这毫无帮助。`sans-serif` 会解析成一种*不差于*你指定的那些字体,而且很可能*更好*。
下面是一个我刚刚遇到的*真实例子*(标点后已恢复空格,因为原文被压缩了):
``
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif
``
这*太荒谬了*,严格来说它比 `font-family: monospace, monospace` 更差。`monospace` 会解析成一种*不差*的字体。
当然,我并不是说*绝无*这样做的理由。考虑 Georgia (https://en.wikipedia.org/wiki/Georgia_(typeface)) 和 Times New Roman (https://en.wikipedia.org/wiki/Times_New_Roman),两者都是微软 Core fonts for the Web (https://en.wikipedia.org/wiki/Core_fonts_for_the_web) 中的衬线字体。但它们的视觉效果大不相同:Georgia 要宽得多。如果出于风格原因你需要这种效果,我不会反对你使用 `font-family: Georgia, serif`。
### a) *最多*只使用一个指定的非网络字体
这是一个例外情况。
考虑 Georgia (https://en.wikipedia.org/wiki/Georgia_(typeface)) 和 Times New Roman (https://en.wikipedia.org/wiki/Times_New_Roman),两者都是微软 Core fonts for the Web (https://en.wikipedia.org/wiki/Core_fonts_for_the_web) 中的衬线字体。但它们的视觉效果大不相同:Georgia 要宽得多。如果出于风格原因你需要这种效果,我不会反对你使用 `font-family: Georgia, serif`。
modernfontstacks.com (https://modernfontstacks.com/) 很有意思。 他们的仓库 (https://github.com/system-fonts/modern-font-stacks) 描述了更多关于不同平台应该使用什么字体的内容。想法不错,但我认为它试图规定得过于细了,其中很多指定字体最好删掉。而且,他们*极其糟糕地*处理了 Courier New——看起来他们的图片是用 macOS 系统的 Courier 制作的。
## 3. 强烈建议*只*使用通用字体系列
所以,也许我们已经去掉了那些本地安装的字体,因为它们没什么用;那 Web 字体呢?
使用 Web 字体比不使用更慢;而且你可能会遇到加载问题;所以我们有了 `font-display` (https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@font-face/font-display)。
但说真的,与其在 block 和 swap 周期、重绘和回流之间纠结权衡,为什么不用用户已有的字体呢?
它不会那么糟。用户甚至可能自己选择了字体。
考虑一下吧。
### a) 没错,即使对于等宽字体也是如此
历史上,`monospace` 的默认字体*很差*。
这主要是微软的错,他们使用了那个糟糕的 Courier New (https://en.wikipedia.org/wiki/Courier_(typeface)#Courier_New),数字化得很差,实际上只有 200–250 的粗细,而不是标准的 400。
后来,Apple 推出了 Menlo (https://en.wikipedia.org/wiki/Menlo_(typeface)),人们很喜欢它,于是开始把这个字体加进字体栈,因为浏览器厂商没有更新 `monospace` 的默认值。事情就这样延续下去。
不过,那些日子已经过去了。现在浏览器的默认字体都更好了。虽然在某些情况下可能还*不够出色*,但再也*不差*了。
所以,把 `Menlo, Monaco, Consolas, Bitstream Vera Sans Mono, Courier, Courier New` 这些都去掉,试试只留下 `monospace` 吧。
这里有一个我刚刚遇到的*真实声明*(标点后已加空格,原文被压缩):
``
font-family: Menlo, Monoaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif
``
如果你曾在字体栈中*故意*使用 `Courier New`,我不确定我们还能不能做朋友。
### b) 事实上,请写成 `monospace, monospace`
这是浏览器历史遗留的一个丑陋问题,似乎在规范文档中找不到,但所有老开发者都记得。
如果你使用 `font-family: monospace;`(显式或隐式),`font-size` *很可能*默认是 81.25% 而不是 100%。(用户可以更改通用字体、基础字体大小和等宽字体的基础大小。)
如果列表中还有第二个字体,就不会出现这个问题;所以 `font-family: my-web-font, monospace;` 没问题,`font-family: monospace, monospace;` 也没问题。
或者,如果你愿意,也可以手动设置字体大小。
如果你使用 Lightning CSS,它*会损坏* `monospace, monospace` (https://github.com/parcel-bundler/lightningcss/issues/1221);所以我目前写作 `monospace, m`。
这个问题只影响 `monospace`。也可能会影响更改语言后的文本,但那是另一回事。
我希望能说服浏览器厂商放弃对 `monospace` 进行字体大小调整,并将其从大概 13px 增加到大概 16px。我想 CSSWG 可能会是提出这个建议的场所。
## 4. 不要在正文中使用 `system-ui` 或 `ui-*`
UI 字体是为简短的 UI 文本设计的,*不是*长文内容。
UI 字体可能不支持你的内容语言:macOS 做得好,但 Windows *不是*,结果就是像 CJK 用户会得到一个糟糕的等宽字体 (https://infinnie.github.io/blog/2017/systemui.html)。
有时,人们甚至故意选择了荒谬的系统 UI 字体——在某些 Android 圈子中很常见。我*推测* `system-ui` 也会让内容显得很荒谬。
w3c/csswg-drafts issue #3658 (https://github.com/w3c/csswg-drafts/issues/3658) 讨论了其中一些问题,结论是 `system-ui` 已被广泛滥用。mdn/content issue #41244 (https://github.com/mdn/content/issues/41244) 最终在 MDN 上增加了一个说明,劝阻不要过度使用。
这些字体系列在很大程度上被用作更好默认字体的替代品。这不是一个好的用法。
我认为 `system-ui` 是个错误。他们当初应该保留 `-apple-system`,并让 `BlinkMacSystemFont` 改成它:当时没有其他平台有类似的有用概念(尽管现在有些有了),而且在标准化之前很久就已经很明显,几乎所有对这个东西的使用都是*滥用*,是在规避浏览器没有更新其考虑不周、过时的通用字体默认值。
我认为 `ui-serif`、`ui-sans-serif` 和*尤其*是 `ui-rounded` 是一个*完全愚蠢*的想法,应该被删除。尤其是因为它们在...任何非 Apple 的平台上都*不期望映射到任何字体*。既然只存在于 Apple,它们就*不需要*放在规范中。它们可以仅仅作为名称以 `-apple-` 开头的字体来暴露。
(什么?我们不再使用前缀了?这看起来像前缀,但实际上不是。)
相似文章
CSS:不可避免的坏部分
一位非Web开发者的个人博客文章讨论了CSS中不可避免的坏部分,包括布局难题、浏览器默认设置和过度使用包装器,同时强调了可处理简单任务的子集。
简单HTML的超凡有效性
一篇博文,论证了简单HTML对于普遍可访问性的持续重要性,并通过一位女性使用PSP浏览器访问政府服务的故事加以说明。
检测并分析任意网站上的字体,揭示其属性与元数据
Typical 是一个工具,可让您检测和分析任何网站上的字体,并显示其属性和元数据。
readable.css
readable.css 是一个CSS框架,为网站提供了合理且美观的基础默认样式,支持亮/暗模式、响应式设计和垂直节奏,强调一致性和语义化HTML。
几个有趣的现代像素字体
本文介绍了几种现代像素字体,包括 Analog Mono、Coral Pixels、Two Slice 和 Geist Pixel,讨论了它们的设计特色以及对 1990 年代亚像素渲染技术的怀旧情怀。