加了 font-display: swap 仍抖动,是因为 fallback 与 web 字体度量偏差超5%,导致布局位移(cls);需对齐 x-height、line-height 等,并确保 preload 正确、format 声明完整、中文字体子集化及 size-adjust 调整。

font-display: swap 为什么加了还是抖
加了 font-display: swap 却仍有抖动,不是策略失效,而是 fallback 字体和 Web 字体在 x-height、line-height、字宽等度量上偏差超过 5%,触发 layout shift(CLS)。浏览器先用系统字体撑开布局,替换时尺寸突变,文字就“跳一下”。这不是加载慢,是排版错位。
- 常见诱因:fallback 字体链混用衬线与无衬线(如
"Georgia"和"Inter") - 没声明
size-adjust或ascent-override等 OpenType 度量对齐属性 - 在 CSS 中用
font-size: 0.9em强制缩放,放大了原始度量偏差
preload 字体必须带 crossorigin 属性
<link rel="preload"> 是唯一能在 HTML 解析阶段就触发字体下载的手段,但缺 crossorigin 就等于没写——哪怕字体跟页面同源,浏览器也直接跳过该请求。
- 正确组合只有这一种:
as="font"+type="font/woff2"+crossorigin(值为空即可) - 没写
crossorigin→ Network 面板里看不到请求,或 Priority 显示为lowest - 写了
crossorigin但服务端没配Access-Control-Allow-Origin: *→ 控制台报 CORS error - 只 preload 首屏确定用到的字重,比如
Inter-Regular.woff2,别把整套 variable font 全 preloaded
@font-face 中 format() 声明不能省
很多项目写了 font-display: swap 却没生效,根源在 @font-face 的 src 没写 format("woff2")。旧版 Safari、某些 WebView 会直接忽略整条规则,退回到默认 font-display: auto,FOIT 回归。
- 务必检查:
src是否只用一个url(),而没兜底多个格式(如 woff2 + woff) - 路径是否绝对(相对路径在
file://或某些 iframe 下易 404) - 是否用
@import引入字体 CSS —— 预加载和解析都会延迟,且无法控制资源优先级 - 正确写法:
@font-face { font-family: "Inter"; src: url("/fonts/Inter.woff2") format("woff2"); font-display: swap; }
中文字体必须子集化 + 布局锁定
中文字体文件动辄 2–5MB,全量加载必然拖慢首屏。即使开了 swap,fallback 字体(如 system-ui)和中文字体的字宽差异极大,FOUT 几乎必然伴随严重跳动。
- 必须做两件事:用工具(如
pyftsubset或在线服务)按实际页面用到的汉字生成子集,体积可压到 200KB 以内 - 在
@font-face中加size-adjust: 102%或ascent-override: 95%(数值需实测)对齐度量 - fallback 字体链要分平台写清楚:
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif - 避免仅靠英文 fallback 蒙混过关,中文环境里它大概率不生效
cap-height 或 descender 上差几个像素,抖动就藏不住。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











