B08 字体与网络字体加载
B08 字体与网络字体加载
摘要:字体由字体族栈、
@font-face声明与加载策略三部分组成。font-display决定字体未就绪时显示什么,swap会先显示回退字体再替换,代价是可观的布局跳动;可变字体用一份文件提供连续字重,适合替代多字重字体包。本文给出字体族栈的组织方式、@font-face完整写法、四种font-display的取舍、度量覆盖减小跳动的做法与子集化策略。
关键词:字体族,@font-face,font-display,可变字体,FOUT
所属:frontend/css / B-进阶 | 上一篇:B07-背景渐变与滤镜 | 下一篇:C00-总结 | 返回:B00-总结
1 引言
引入网络字体后常见的三类问题:首屏文字长时间空白、字体加载完成时页面跳动、一个中文字体包动辄数兆。三者都由加载策略而非字体本身决定。
本文给出字体声明与加载的完整做法。范围见表 1-1。
| 项 | 本文覆盖 | 本文不覆盖 |
|---|---|---|
| 声明 | @font-face、src、unicode-range |
字体授权与商业使用 |
| 加载 | font-display 四值、预加载、回退字体度量 |
服务端字体注入 |
| 组织 | 字体族栈、系统字体栈、可变字体 | 字体设计本身 |
表 1-1 本文覆盖范围
2 预备知识
| 项 | 要求 | 核对方式 |
|---|---|---|
| 环境 | 本地服务器可用 | 浏览器能打开 localhost |
| 文件 | css-practice/fonts.html |
编码 UTF-8 |
| 浏览器 | Chrome 130+,Network 面板可用 | 能限速观察字体加载 |
| 前置 | A03 | 字号与行高已掌握 |
表 2-1 环境与前置要求
3 原理与实现
3.1 字体的两段加载
浏览器先用回退字体绘制,字体到达后替换,替换时机由 font-display 决定,如图 3-1 所示。
flowchart TD
A["页面开始解析"] --> B["回退字体立即绘制"]
B --> C{"font-display 取值"}
C -->|block| D["最多隐藏约 3 秒"]
C -->|swap| E["立即显示回退字体"]
C -->|fallback| F["短阻塞后用回退字体"]
C -->|optional| G["超时则本页不再替换"]
D --> H["字体到达后替换 产生跳动"]
E --> H
F --> H
G --> I["下一页才使用新字体"]
图 3-1 font-display 控制替换时机与阻塞时长
图上可见:四种取值只在「阻塞多久」与「是否替换」两个维度上不同;
swap换来的可读性与布局跳动是一对取舍。
3.2 完整实现
/* 运行环境:Chrome 130+;css-practice/fonts.css */
/* 1 系统字体栈:零加载成本,正文首选 */
:root {
--font-sans: system-ui, -apple-system, "Segoe UI", "Noto Sans SC",
"PingFang SC", "Microsoft YaHei", sans-serif;
--font-mono: ui-monospace, "Cascadia Code", Consolas, monospace;
}
/* 2 网络字体:一份可变字体覆盖多个字重 */
@font-face {
font-family: "Brand Sans";
src: url("/fonts/brand-sans.woff2") format("woff2") tech(variations),
url("/fonts/brand-sans-static.woff2") format("woff2");
font-weight: 100 900;
font-style: normal;
font-display: swap;
unicode-range: U+0000-00FF, U+2000-206F, U+3000-303F;
}
/* 3 回退字体度量覆盖:让替换时的跳动可控 */
@font-face {
font-family: "Brand Sans Fallback";
src: local("Arial");
size-adjust: 97%;
ascent-override: 95%;
descent-override: 25%;
line-gap-override: 0%;
}
body {
font-family: "Brand Sans", "Brand Sans Fallback", var(--font-sans);
font-synthesis-weight: none; /* 无对应字重时不合成粗体 */
}
h1 {
font-family: var(--font-sans);
font-variation-settings: "wght" 700, "opsz" 48;
font-optical-sizing: auto;
}
code { font-family: var(--font-mono); }
font-display 四值的取舍见表 3-1。
| 取值 | 阻塞期 | 替换行为 | 适用场景 |
|---|---|---|---|
auto |
由浏览器决定 | 同 block |
无明确要求时的默认 |
block |
约 3 秒 | 到达后替换 | 图标字体、必须一致的标题 |
swap |
极短 | 到达后替换 | 正文,可读性优先 |
fallback |
约 100 毫秒 | 到达后替换,超时不再换 | 可减少跳动,适合正文 |
optional |
约 100 毫秒 | 超时则本页不替换 | 弱网、装饰性字体 |
表 3-1 font-display 取值与阻塞、替换行为
中文字体体积控制见表 3-2。
| 手段 | 做法 | 效果 |
|---|---|---|
选 woff2 |
只提供 format("woff2") |
比 woff 小约 30% |
| 子集化 | 按 unicode-range 切片或按页打包 |
只下载用到的字符集 |
| 可变字体 | 一份文件覆盖 100~900 字重 | 取代 4~6 个静态字重文件 |
| 预加载 | <link rel="preload" as="font" crossorigin> |
提前发起下载,缩短阻塞 |
| 度量覆盖 | size-adjust 等覆盖属性 |
降低替换时的布局跳动 |
表 3-2 五类体积与跳动控制手段
4 验证与讨论
- 在 Network 面板把网速限速到 Slow 3G,刷新页面,观察正文先用回退字体绘制再替换。
- 把
font-display改为block,确认首屏文字空白约 3 秒后出现。 - 改为
optional并限速,确认本页不再替换,刷新后才使用网络字体。 - 注释掉
size-adjust与ascent-override,在替换瞬间观察标题位置的偏移量。
<!-- 预加载与跨域:字体必须带 crossorigin,否则二次下载 -->
<link
rel="preload"
href="/fonts/brand-sans.woff2"
as="font"
type="font/woff2"
crossorigin
/>
| 检查项 | 预期结果 | 说明 |
|---|---|---|
| 替换可观察 | 限速后可见回退字体先出现 | 图 3-1 |
| 阻塞差异 | block 下首屏空白约 3 秒 |
表 3-1 |
| 预加载生效 | 字体请求出现在文档早期 | 3.2 节 link 代码 |
| 跳动可控 | 加度量覆盖后偏移显著减小 | 表 3-2 |
表 4-1 字体加载的四项验收
讨论与局限。 size-adjust 需要按回退字体实测调整,换回退字体就要重测。另,unicode-range 切片会增加请求数,字符集分散时反而更慢,需按站点实际字符分布评估。
5 常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 首屏文字长时间空白 | 用了 block 且字体未预加载 |
改 swap 或加 preload |
| 字体加载后整页跳动 | 回退与网络字体度量差异大 | 加 size-adjust 等度量覆盖 |
| 字体提示已下载但仍二次请求 | 预加载缺 crossorigin |
补 crossorigin 属性 |
| 中文页面体积过大 | 全字符集打包 | 子集化或改用系统字体栈 |
| 可变字重不生效 | font-weight 未声明区间 |
font-weight: 100 900 |
| 粗体看起来是被拉粗的 | 浏览器合成了字重 | 提供对应字重或设 font-synthesis-weight |
表 5-1 字体加载的六类问题
6 结论
| 序号 | 结论 | 依据 |
|---|---|---|
| 1 | font-display 在阻塞与替换间取舍 |
图 3-1 |
| 2 | 正文用 swap,装饰字体用 optional |
表 3-1 |
| 3 | 预加载必须带 crossorigin |
4 节代码 |
| 4 | 度量覆盖是降低跳动的直接手段 | 表 3-2 |
表 6-1 结论汇总
- 上一篇:B07-背景渐变与滤镜
- 下一篇:C00-总结
- 返回:B00-总结 | 科目 README
参考文献
[1] MDN Web Docs · @font-face,https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face(访问于 2026-10-31)
[2] web.dev · 网络字体最佳实践,https://web.dev/articles/font-best-practices(访问于 2026-10-31)

评论 0
还没有评论,快来抢沙发吧~