FORMA

字体优化策略

Web 字体(@font-face)常是首屏体积与 LCP 的大头,尤其中文字库。策略不当会出现文字长时间不可见(FOIT)、回退字体与 Web 字体切换导致布局跳动(FOUT/CLS)。本文与 排版与文本 中的 Web 字体概要衔接。

演示(需登录):字体加载 Demo

优化目标

问题对策
文件过大子集化、WOFF2、变量字体按需
加载阻塞font-display、preload、避免 @import
切换抖动回退栈、font-size-adjustsize-adjust(@font-face)

font-display(加载时间轴)

写在 @font-face 内,控制阻塞期 / 交换期 / 失败期的渲染策略:

行为概要
auto由浏览器决定(常偏阻塞)
block短阻塞 + 长交换(可能 FOIT)
swap极短阻塞 + 长交换;文字尽快可见,可能 FOUT(正文常用)
fallback极短阻塞 + 短交换,超时则放弃 Web 字体
optional极短阻塞、无交换;未赶上则整页用回退字体(装饰字体)
css
@font-face {
    font-family: "MyFont";
    src: url("/fonts/my.woff2") format("woff2");
    font-display: swap;
}

格式与 src 列表

优先 WOFF2(Brotli 压缩,现代浏览器普遍支持),再回退 WOFF:

css
@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 条目:

css
@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-faceunicode-range 匹配;与 local() 回退可组合(用户已安装字体时跳过下载)。

预加载(preload)

首屏关键字体(Logo、大标题)可在 <head> 提前请求:

html
<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

回退字体栈

css
body {
    font-family: "MyWebFont", "PingFang SC", "Microsoft YaHei", sans-serif;
}

font-size-adjust

按首选字体的 x 高度比例调整回退字号,减少切换时行高跳动:

css
body {
    font-family: "MyWebFont", Arial, sans-serif;
    font-size-adjust: 0.5; /* 依字体 aspect value 调整 */
}

@font-face 度量覆盖(较新)

size-adjustascent-overridedescent-overrideline-gap-override 可让回退字体度量更接近 Web 字体,进一步降低 CLS(需查浏览器支持)。

变量字体

单个文件包含多轴(字重、宽度等),适合需要多种字重的设计;若只用一种字重,静态子集文件可能更小。按实际轴使用情况评估体积。

字体子集化

从完整字库提取页面实际用到的字符,生成小体积 .woff2

工具

工具说明
fonttools / pyftsubsetGoogle Fonts 等常用,可指定 Unicode 范围
font-spider扫描 HTML/CSS 用到的字;会覆盖原字体文件,务必备份
Font Squirrel Webfont Generator适合少量字符、手工场景

font-spider 流程要点

  1. @font-face 使用本地路径,页面 HTML 中出现需保留的汉字。
  2. 运行 font-spider index.html 生成子集。
  3. 保留原始字体备份(如 raw/),构建时复制到 dist/ 再子集化。

中文分层策略

  • 标题/Logo:静态子集,仅打包出现的字。
  • 正文:优先系统字体栈,避免加载全量中文 Web 字体。
  • UGC/不可预知内容:常用字基础包 + 动态补字(需自建服务或第三方),复杂度高。

实践路径

  1. 能不用 Web 字体则不用;中文正文优先系统 UI 字体。
  2. 必须用:WOFF2 + font-display: swap(或 optional 装饰字)。
  3. 首屏关键字体:preload + crossorigin
  4. 中文按需子集;英文可考虑 CDN(自带子集,注意隐私与合规)。
  5. 监控 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子集化工具

Series

css

6 / 20