GANKUDADIZ
BACK_TO_BLOG
TECH_LOG :: 2026.07.16

网页字体:TTF、WOFF2 和子集化

Avatar
By Gankudadiz · 1 min read · 14 views

之前我博客用了一款中文字体,TTF 格式,7MB。首次加载的时候浏览器响应太久了,后来换成 WOFF2 并做了子集化,加载速度才正常。

下面让AI整理一下这几个概念的关系,以及我自己踩坑之后觉得比较有用的几条经验。


字体家族和网页交付物是两回事

同一款字体,实际包含了好几层东西。

字体家族是第一步,比如霞鹜新晰黑、文楷,这决定了字形长什么样。同一个字体家族下面可以有不同的字重和变体,Regular、Light、Screen、Plus,同样的字形设计,但粗细和适用场景不一样。

再往下才是文件格式。TTF、OTF、WOFF、WOFF2 这一层不改变字形,只改变怎么打包和怎么传输。最后还有字符覆盖的问题:你是把整个字库打包进去,还是只取了其中一部分。

我之前跑到 GitHub release 里翻"官方 WOFF2",找不到很正常。很多开源中文字体项目默认发的是桌面安装包,TTF 或者 OTF 打个 zip 包就发布了,并不是现成的 webfont。网站要用,得自己转格式,或者自己做子集。

换句话说,找不到 WOFF2 不一定是你翻错了页面,可能是上游本来就不以 Web 分发为主。


TTF 和 WOFF2 的关系

简单说:TTF/OTF 是轮廓数据本体,WOFF/WOFF2 是面向 Web 的压缩容器。WOFF2 不是什么新的字形设计,只是更适合浏览器下载的封装方式。

一般流程是源文件 TTF/OTF 转成 WOFF2,体积会降一些,现代浏览器拿到后优先用 WOFF2 渲染。

不过全量中文 TTF 转 WOFF2,体积虽然能明显变小,但别指望从几 MB 直接掉到几十 KB。CJK 全字库包含的字形太多了,压缩有上限。

还有一个 gzip 的问题。服务器端可能对 TTF 再压一层,但字体场景里,原生 WOFF2 通常比"TTF + gzip"更合适,少一层解压和 MIME 类型的麻烦。


子集化比换格式影响更大

子集的意思很简单:不打包整本字典,只打包页面大概率会用到的字。

中文全字库动辄几千到上万个字形,桌面字体 7MB、13MB、20MB 都常见。但网页正文真正用到的其实没那么多。常用汉字 3500 到 6500 个、ASCII 和数字、中英文标点、少量技术符号,够了。子集之后,体积经常能再掉一个数量级。

这也是为什么有些站看起来字体挺多、还挺花,首屏却不慢。主正文用的是小 WOFF2 或者干脆系统字体,花体和手写体只给标题和短文本用,没真正用到的字体根本不会触发下载。有的方案还会按 unicode-range 把字体切成很多小块,按需加载。

另外提醒一句:LiteScreen 这些变体名字不等于"适合网页秒开"。Lite 只是相对完整版精简了一点,但仍然是十几 MB 的 TTF 的情况很常见。Screen 是更适合屏幕显示,有时候反而比普通版更大。是不是 Web 友好,要看有没有 WOFF2、有没有子集或分片,不要看名字。


font-display 管的是等待策略

格式和体积决定下载快慢,font-display 决定下载期间页面怎么显示。

block:字体没到之前,相关文字可能先空白一小段时间。swap:先用系统字体顶着,自定义字体到了再替换。fallbackoptional 更保守,减少了后期切换的闪动,但自定义字体出现的概率也低了。

如果正文绑了大中文字体还用 block,弱网冷启动的时候很容易翻车:正文区域一片空白,只有代码块先蹦出来了。大多数内容站,正文更适合 swap,先保证能读,再追求最终字形一致。

preload 也要谨慎。它会直接把字体资源抬到关键请求链上。小文件 preload 有意义,全量大中文库 preload 很可能跟其他 CSS 和 JS 抢带宽,得不偿失。


实际怎么选

个人博客和内容站正文。 我自己的优先级是:系统字体栈最快,零下载,先保证能用。其次是小体积子集 WOFF2 配 swap。全量 WOFF2 算能用但不够好。全量 TTF 直接上网页是最不推荐的。正文要的是长时间阅读的稳定性,不是花哨。

标题、Logo、短文案。 这里可以用更有性格的字体,手写风、二次元风都行。但最好是单独的、体积小的文件,只作用在短文本上,别 preload 一堆备选花体,接受个别生僻字回退到系统字体。

后台、文档、工具站。 系统字体往往已经够了。除非品牌一致性要求很强,否则没必要为后台再挂一套中文 Web 字体。


优化顺序

如果已经觉得字体拖慢了页面,我觉得最先该动的不是换格式,而是改显示策略。正文 block 改成 swap。这个改动不减小下载量,但能避免"字到了用户却看不见"的情况,算是止血。

然后是缓存和 MIME 配置。生产环境给 .woff2.woff.ttf 设好 Content-Type,做长期缓存。注意上了 immutable 之后,字体内容有变更必须改文件名,不能原地覆盖。

接下来考虑 TTF 换 WOFF2,有改善但别抱太高期望。

真正影响中文站冷启动体感的是子集。这一步做完,体积经常能掉一个数量级。

CDN 放在最后考虑。它解决的是就近分发和并发问题,但如果首包本身就 7MB,CDN 也只是更快地把大文件传过去,根上没解决体积。

一句话:先让文字尽快可读,再把字体文件变小,最后才谈分发网络。


子集的取舍

子集不是免费的。越小越快,但也越小越可能缺字。缺字的时候浏览器会回退到字体栈里的下一个字体,文字看起来就不统一了。

对个人博客来说,这个代价通常可以接受。生僻字偶尔回退,总比每次新访客都扛一整个完整字库强。如果你的站点经常出现人名、古文、生僻专业术语,那字表就要保守一些,或者准备"常用子集加回退到全量或系统字体"的策略。

工具层面,常见的路线是 fonttools 这类方案:从 TTF 生成 WOFF2,再按你指定的文本或字表裁剪。上游官方不提供 webfont,不代表不能自己做。

评论 (0)

还没有评论,来留下第一条想法吧。

[DRAFT_RESTORED]

已恢复你上次未提交的评论草稿。

正文草稿仅保留在当前标签页;若浏览器已记住你的身份信息,昵称、邮箱和个人网站可在其他文章页自动回填。

ACTION:

[AUTHOR_PROFILE_REMEMBERED]

浏览器已记住你的昵称、邮箱和个人网站,切换到其他文章页时会自动回填。