介绍
网络字体增强了设计,但需要付出代价。加载自定义字体时,浏览器必须决定:显示不可见文本(FOIT - 不可见文本的 Flash)或显示后备字体(FOUT - 无样式文本的 Flash)。任一选择都会影响 CLS(累积布局偏移) 和用户体验。本文介绍了可靠加载字体同时最小化布局变化的策略。
字体显示描述符
@font-face 中的 font-display 属性控制加载过程中字体的显示方式:
@font-face {
font-family: 'MyFont';
src: url('/fonts/myfont.woff2') format('woff2');
font-display: swap;
}
| 价值 | 行为 | 使用案例 |
|---|---|---|
| 占位符_0 | 浏览器默认(通常为 FOIT) | 默认 |
| 占位符_0 | 不可见文本长达约 3 秒,然后交换 | 区块周期短 |
| 占位符_0 | 立即后备字体,准备好后交换 | 最大可读性 |
| 占位符_0 | 不可见文本 ~100ms,回退 ~3s,然后交换 | 平衡 |
| 占位符_0 | 短块,可选下载 | 连接速度慢 |
swap 是最常见的选择 - 它立即显示后备文本,然后在加载自定义字体时进行交换,完全消除 FOIT。
预加载关键字体
在 <head> 中使用 <link rel="preload"> 来提前开始字体下载:
<link rel="preload" href="/fonts/myfont.woff2" as="font" type="font/woff2" crossorigin>
对于从不同来源加载的字体,甚至通过 CDN 提供的同源字体,crossorigin 属性是必需的。如果没有它,预载将被忽略。
自托管与 CDN
| 方法 | 优点 | 缺点 |
|---|---|---|
| 自托管 | 完全控制,无需额外的DNS查找、缓存控制 | 带宽成本 |
| 谷歌字体/CDN | 快速边缘传送,自动子集 | 额外的 DNS + TLS 握手 |
对于关键字体,自托管通常表现更好,因为它消除了与字体提供商的额外连接。如果必须使用第三方字体服务,请使用 preconnect:
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
字体子集化
将每个字形包含在字体文件中会浪费带宽。 子集化删除未使用的字符:
# Using pyftsubset (fonttools)
pyftsubset Roboto-Regular.ttf --unicodes="U+0020-007E,U+00A0-00FF"
大多数 CDN 字体服务会自动执行此操作。对于自托管字体,请为您支持的每种语言生成子集。 glyphhanger 或 fonttools 等工具可以输出小至 10-20 KB 而不是 100+ KB 的文件。
WOFF2:现代标准
WOFF2(Web 开放字体格式 2)提供比 WOFF 更好 30-50% 的压缩:
@font-face {
font-family: 'MyFont';
src: url('/fonts/myfont.woff2') format('woff2'),
url('/fonts/myfont.woff') format('woff'); /* fallback */
}
所有现代浏览器都支持 WOFF2。使用它作为主要格式,并使用 WOFF 作为备用格式。
通过大小调整防止布局移位
@font-face 中的 size-adjust 描述符可让您标准化指标,以便后备字体和自定义字体占据相同的空间:
@font-face {
font-family: 'Fallback';
src: local('Arial');
size-adjust: 95%;
ascent-override: 85%;
descent-override: 20%;
}
使用 size-adjust 计算器(Chrome 开发者工具 > 渲染 > 字体大小调整)等工具来查找正确的值。当字体交换时,这会显着降低 CLS。
完整的优化方案
<head>
<!-- Preconnect to font origin -->
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<!-- Preload the main font -->
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
</head>
@font-face {
font-family: 'Main';
src: url('/fonts/main.woff2') format('woff2');
font-display: swap;
}
body {
font-family: 'Main', 'Fallback', sans-serif;
}
结论
优化 Web 字体需要采用多层方法:使用 font-display: swap 来防止 FOIT、预加载关键字体、对文件进行子集化、提供 WOFF2 并应用 size-adjust 来最小化 CLS。这些技术共同确保了快速、稳定和美观的排版。

