资讯文章 资讯 · NEWS
中文字体把首屏拖慢了两秒:目录站的 font-display、预加载和字体子集该怎么配
2026-10-22 约 2,245 字 预计阅读 6 分钟 yiyunkj
中
目录站的页面结构天生对字体不友好:首页一屏要摆几十个条目名、分类名、标签,文字密度极高。一旦自定义字体加载慢,用户看到的是一片空白或者先出系统字再猛地跳成目标字,两种都难看。中文字体的体积又比拉丁字体大一个数量级,这个问题在中文站上被放大了好几倍。

图片来源:网络,版权归原作者所有,侵权请联系删除
先搞清楚 FOIT 和 FOUT 是两种病
浏览器拿到 @font-face 之后,字体文件没下载完之前有两种处理方式。一种是先不显示文字,等字体到位再一起渲染,用户看到一段空白,这叫 FOIT(Flash of Invisible Text,隐形文字闪烁)。另一种是先用系统字体把文字画出来,字体到位后再替换,用户看到文字换了个样子,这叫 FOUT(Flash of Unstyled Text,无样式文字闪烁)。
font-display 这个 CSS 属性就是用来选哪种病的:
| 取值 | 行为 | 目录站适用场景 |
|---|---|---|
| block | 先空白等待,超过约 3 秒才降级 | 基本不用,首屏最容易白屏 |
| swap | 立即用系统字显示,字体来了就换 | 正文、条目名,默认选择 |
| fallback | 短暂空白(约 100ms),之后用系统字,且超时后不再替换 | 对字体一致性要求不高的页面 |
| optional | 空白期极短,若字体没赶上首屏渲染就整页不再替换 | 追求 CLS 稳定的页面 |
swap 解决了白屏,但没解决抖动
很多人填上 font-display: swap 就以为完事了。实测里最常见的情况是:系统字先把一整屏条目名画出来,两秒后字体加载完成,所有文字同时换形,行高、字宽全变,页面往下推了一截。用户正要点某个条目,手指落下去点到了另一个。
这正是 CLS(累计布局偏移)扣分的典型场景。web.dev 的字体显示文档里说得很直接:FOIT 和 FOUT 在自定义字体替换系统字体时,对 CLS 的影响是一样的。swap 只是把白屏问题换成了抖动问题。
要用 optional,就得配 preload
官方给的解法是 preload 配合 font-display: optional:用 <link rel="preload"> 把字体提到最早加载,让它在首屏渲染前到位;同时用 optional 约定「赶不上这次渲染就别换了,下次访问再说」。这样第一次访问可能用的是系统字,但页面不抖,第二次访问有缓存,字体已经在了。
<link rel="preload" href="/fonts/brand-subset.woff2" as="font"
type="font/woff2" crossorigin>
但同一份文档也提醒:过度使用 preload 会对加载指标产生负面影响,它会抢占带宽,把真正关键的 CSS 和首屏条目数据挤到后面。目录站上最多 preload 一到两个字体文件,多了就是负优化。改完务必用 Lighthouse 前后对比一次,别凭感觉。
中文字体的真正解法是子集化
一套完整的中文字体,woff2 压缩后通常仍有数兆字节。不管 font-display 怎么配,几兆的文件在移动网络下都是灾难。真正有用的动作是把字体砍小:
- 静态子集:只保留站点实际用到的字。目录站的条目名、分类名、按钮文案、导航文字加起来通常几千字,用 pyftsubset 之类的工具按字表生成子集,体积能降一到两个数量级。
- unicode-range 分片:按Unicode 区段把字体切成几片,浏览器只下载页面实际命中的那几片。适合条目名里混排多语种、繁体字的目录站。
- 格式只用 woff2:woff2 的压缩率明显优于 woff 和 ttf,现代浏览器全都支持,没必要再留旧格式的 fallback 分支。
图标字体该退役了
早期目录站喜欢把分类图标做成图标字体,一个字体文件装几百个图标。问题是它同样有 FOIT/FOUT 问题——图标加载慢的时候,条目名前面会出现空白方框或者乱码字符。
更稳的做法是 SVG sprite:把所有图标拼成一个 SVG,页面内联引用。它是 HTML 的一部分,跟着首屏一起渲染,没有额外的字体加载等待,也不会出现豆腐块。图标字体在目录站上基本没有留下来的必要。
最省事的方案:系统字体栈
如果站点对品牌字体没有硬性要求,直接用系统字体栈是最优解:零下载、零 FOUT、零 CLS,首屏最快。
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC",
"Microsoft YaHei", "Noto Sans CJK SC", sans-serif;
不同操作系统各自渲染成自己最顺眼的那一套,用户反而觉得「这个站很流畅」。真要用品牌字体,就只用在标题和 Logo 上,正文条目名继续走系统字体栈,把风险控制在最小范围。
一条可以直接抄的配置
综合下来,目录站比较稳的字体配置是这样的:
- 正文与条目名:系统字体栈,不加载任何 web font
- 标题与品牌位:子集化后的 woff2,
font-display: swap,仅 preload 一个文件 - 对 CLS 极度敏感的落地页:改用
font-display: optional+ preload - 图标:SVG sprite,不用图标字体
- 改动后:Lighthouse 跑一次,看 CLS 和 LCP 有没有变差,别只看感觉
字体优化在目录站上的收益,主要不来自「加载更快」,而来自「页面不再抖」。用户点条目的时候页面是稳的,这件事比字体好不好看重要得多。
另外补一句工具层面的变化:Lighthouse 从 13 版开始,原本独立的 font-display 审计被并进了 Font display insight。如果你在升级后找不到原来的那一项,不是站点变好了,是审计换了位置。