浏览器怎么加载网页字体
适合谁看:想搞清楚网页字体从请求到显示经历了什么、为什么会「白屏」或「跳一下」的前端开发者。
@font-face 的基本写法见《在网页里使用字体:@font-face 的现代写法》。本页讲背后的过程,后面几页的优化都从这里出发。
一次加载的顺序
- 下载 HTML,发现 CSS。 字体 CSS 写在
<link>里会较早开始下载;写在@import里要等外层 CSS 下载完才开始。 - 解析 CSS,登记
@font-face。 这一步只是登记「有这么一个字体、文件在哪里」,不会下载字体文件。 - 排版时发现要用它。 页面上某段文字的
font-family用到了这个字体,并且文字里的字符落在它的unicode-range里,浏览器才开始下载对应的文件。 - 等待期间先用别的字体。 字体没到时,按
font-display的规则,要么先不显示文字,要么先用备用字体显示。 - 字体到了,重新排版。 换成新字体后,字宽、行高不同,段落会重新折行,这就是「跳一下」。
所以字体文件开始下载的时间,比 HTML、CSS 都晚,常常排在关键请求的最后面。
「白屏」和「跳一下」
| 现象 | 常见叫法 | 原因 |
|---|---|---|
| 文字区域空白一段时间 | FOIT(隐形文字闪烁) | 浏览器在等字体,期间文字不画出来 |
| 先显示系统字体,然后换掉 | FOUT(无样式文字闪烁) | 先用备用字体,字体到了再替换 |
CSS 规范对 font-display 的建议是:block 最多等约 3 秒;swap、fallback、optional 只等很短的时间(建议不超过 100 毫秒)就先显示备用字体。中文页面字体大,block 会让读者盯着空白很久,所以一般用 swap,见《加载策略:font-display、预连接和预加载》。
跨域字体要允许跨域
字体文件放在另一个域名时,服务器必须返回 Access-Control-Allow-Origin 响应头,否则浏览器会拒绝使用。自己部署字体时要记得配置。
中文为什么特别
一款中文字体通常有几万个字形,单个文件常有几 MB 到十几 MB。直接引用整个文件,字体要很久才能显示。解决办法就是把它拆成很多小文件,每个文件用 unicode-range 标明包含哪些字,浏览器只下载用到的那几片。原理见《中文网页字体为什么要拆分子集》,动手做见《动手拆子集:pyftsubset》 和《按字分片:cn-font-split》。
这篇文档对你有帮助吗?
谢谢你的反馈!