字体优化策略
Web 字体(@font-face)常是首屏体积与 LCP 的大头,尤其中文字库。策略不当会出现文字长时间不可见(FOIT)、回退字体与 Web 字体切换导致布局跳动(FOUT/CLS)。本文与 排版与文本 中的 Web 字体概要衔接。
演示(需登录):字体加载 Demo
优化目标
| 问题 | 对策 |
|---|---|
| 文件过大 | 子集化、WOFF2、变量字体按需 |
| 加载阻塞 | font-display、preload、避免 @import |
| 切换抖动 | 回退栈、font-size-adjust、size-adjust(@font-face) |
font-display(加载时间轴)
写在 @font-face 内,控制阻塞期 / 交换期 / 失败期的渲染策略:
| 值 | 行为概要 |
|---|---|
auto | 由浏览器决定(常偏阻塞) |
block | 短阻塞 + 长交换(可能 FOIT) |
swap | 极短阻塞 + 长交换;文字尽快可见,可能 FOUT(正文常用) |
fallback | 极短阻塞 + 短交换,超时则放弃 Web 字体 |
optional | 极短阻塞、无交换;未赶上则整页用回退字体(装饰字体) |
@font-face {
font-family: "MyFont";
src: url("/fonts/my.woff2") format("woff2");
font-display: swap;
}
格式与 src 列表
优先 WOFF2(Brotli 压缩,现代浏览器普遍支持),再回退 WOFF:
@font-face {
font-family: "MyFont";
src:
url("/fonts/my.woff2") format("woff2"),
url("/fonts/my.woff") format("woff");
font-weight: 400;
font-style: normal;
font-display: swap;
}
可用 unicode-range 拆分多文件,浏览器仅在使用到对应字符时下载该 @font-face 条目:
@font-face {
font-family: "MyFont";
src: url("/fonts/latin.woff2") format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153;
}
@font-face {
font-family: "MyFont";
src: url("/fonts/cjk.woff2") format("woff2");
unicode-range: U+4E00-9FFF;
}
同一 font-family 下多条 @font-face 按 unicode-range 匹配;与 local() 回退可组合(用户已安装字体时跳过下载)。
预加载(preload)
首屏关键字体(Logo、大标题)可在 <head> 提前请求:
<link
rel="preload"
href="/fonts/critical.woff2"
as="font"
type="font/woff2"
crossorigin
/>
crossorigin必填(与@font-face跨域规则一致),否则预加载可能无效。- 勿滥用:占用带宽,可能挤占 HTML/CSS/JS。
避免在 CSS 顶部用 @import url(...) 拉字体——会串行化请求;优先 HTML <link> 或打包进主 CSS。
减轻 FOUT / CLS
回退字体栈
body {
font-family: "MyWebFont", "PingFang SC", "Microsoft YaHei", sans-serif;
}
font-size-adjust
按首选字体的 x 高度比例调整回退字号,减少切换时行高跳动:
body {
font-family: "MyWebFont", Arial, sans-serif;
font-size-adjust: 0.5; /* 依字体 aspect value 调整 */
}
@font-face 度量覆盖(较新)
size-adjust、ascent-override、descent-override、line-gap-override 可让回退字体度量更接近 Web 字体,进一步降低 CLS(需查浏览器支持)。
变量字体
单个文件包含多轴(字重、宽度等),适合需要多种字重的设计;若只用一种字重,静态子集文件可能更小。按实际轴使用情况评估体积。
字体子集化
从完整字库提取页面实际用到的字符,生成小体积 .woff2。
工具
| 工具 | 说明 |
|---|---|
| fonttools / pyftsubset | Google Fonts 等常用,可指定 Unicode 范围 |
| font-spider | 扫描 HTML/CSS 用到的字;会覆盖原字体文件,务必备份 |
| Font Squirrel Webfont Generator | 适合少量字符、手工场景 |
font-spider 流程要点
@font-face使用本地路径,页面 HTML 中出现需保留的汉字。- 运行
font-spider index.html生成子集。 - 保留原始字体备份(如
raw/),构建时复制到dist/再子集化。
中文分层策略
- 标题/Logo:静态子集,仅打包出现的字。
- 正文:优先系统字体栈,避免加载全量中文 Web 字体。
- UGC/不可预知内容:常用字基础包 + 动态补字(需自建服务或第三方),复杂度高。
实践路径
- 能不用 Web 字体则不用;中文正文优先系统 UI 字体。
- 必须用:WOFF2 +
font-display: swap(或optional装饰字)。 - 首屏关键字体:
preload+crossorigin。 - 中文按需子集;英文可考虑 CDN(自带子集,注意隐私与合规)。
- 监控 CLS,必要时
font-size-adjust/ 度量覆盖。
参考文献
以下链接在编写时均可正常访问:
| 资料 | 说明 |
|---|---|
| MDN:@font-face | 字体声明 |
| MDN:font-display | 阻塞/交换时间轴 |
| MDN:font-size-adjust | 回退字号匹配 |
| MDN:rel=preload | 字体预加载 |
| web.dev:Best practices for fonts | 性能与加载策略(英文) |
| W3C:CSS Fonts Module Level 4 | 规范(英文) |
| fonttools | 子集化工具 |
相关文章
Less 基础与核心语法
Less 是 JavaScript 实现的 CSS 预处理器,在 CSS 语法上扩展变量(@)、嵌套、混合、运算与函数,编译为普通 CSS 后由浏览器加载;本文覆盖安装、CLI、构建工具集成与全部核心语法。
Sass 简介与安装
Sass(Syntactically Awesome Style Sheets)是 CSS 预处理器,在 CSS 语法上增加变量、嵌套、混合、模块、控制指令等;有 SCSS 与缩进语法两种源码语法,官方实现为 Dart Sass。
模块与控制流:@use、内置函数、@if/@for/@each
Dart Sass 推荐用 @use/@forward 替代已弃用的 @import;内置 sass:* 模块提供颜色、字符串、列表、Map、数学等函数;@if/@for/@each/@while 用于条件与循环生成样式。
复用机制:Mixin 与继承
Mixin(@mixin/@include)支持参数与 @content,适合动态样式;@extend 与 %placeholder 通过合并选择器复用完全相同的静态样式,减少 CSS 体积。
语法基础:变量、嵌套与运算
Sass 语法基础:$ 变量与插值、选择器嵌套与 & 父选择器引用、数学/颜色/字符串运算、三种注释语法及与原生 CSS 嵌套的关系。
颜色与背景
color 设置前景(多为文字)色;background-* 设置元素背景(颜色、图像、渐变)。二者共同决定对比度与视觉层次,直接影响 无障碍 阅读体验。排版中的文本颜色用法见 排版与文本。