font-display: swap 会导致布局抖动,因其替换字体时因ascent、descent、line-gap差异引发行高和基线重算,造成cls;font-size-adjust仅稳定x-height,不修正baseline偏移,safari不支持;ascent-override等才是精准修复核心,需实测字体度量值并配合font-optical-sizing: none使用。

font-display: swap 为什么会导致布局抖动
swap 的本意是“先显示后备字体,再换自定义字体”,但它不保证视觉稳定——只要后备字体和 Web 字体的 ascent、descent、line-gap 不一致,浏览器就会在替换时重算行高和基线位置,引发文字区域高度突变,连带周围元素跳动(CLS)。这种抖动在菜单、标题、按钮里特别明显,本地测不出是因为字体缓存掩盖了首次加载的 metrics 差异。
font-size-adjust 能做什么,又不能做什么
font-size-adjust 通过控制 x-height 一致性来缓解跳动,但它只影响字号缩放逻辑,不修正 baseline 偏移。Chrome 和 Firefox 支持较好,Safari 目前仍忽略该属性(截至 2026 年 4 月)。所以它适合做辅助,不能当主力。
- 值设为
0.5表示“让所有字体的 x-height 都按目标字体的 50% 来缩放”,需先用font-synthesis: none禁用浏览器自动合成 - 必须配合
font-family回退链使用,例如font-family: 'Inter', system-ui, sans-serif,否则无参照基准 - 对中文字体效果有限——多数中文字体 x-height 差异小,但 baseline 偏移大,这时得靠
ascent-override
真正管用的 baseline 对齐:ascent-override / descent-override
Chrome 125+ 开始支持 ascent-override、descent-override 和 line-gap-override,这才是精准修复抖动的核心手段。它们直接覆盖字体原始度量值,让后备字体“假装”和 Web 字体有一样的基线结构。
- 先用
@font-face中的src加载一个 .woff2 文件,再用 Chrome DevTools → Elements → Computed → Font metrics 查看实际数值 - 把查到的
ascent值(比如1024)换算成百分比:ascent-override: 100%(相对 font-size) - 务必加
font-optical-sizing: none,否则光学缩放会干扰 override 效果 - 示例写法:
@font-face { font-family: 'Inter'; src: url('inter.woff2') format('woff2'); font-display: swap; ascent-override: 95%; descent-override: 25%; line-gap-override: 0%; font-optical-sizing: none; }
fallback 字体栈选错,再好的 override 也白搭
如果 font-family 列表里混用衬线与无衬线(比如 'Georgia', 'Inter'),或用了 metrics 差距极大的系统字体(如 'Times New Roman'),baseline 强制对齐后仍可能因字宽差异导致水平重排。这不是 override 能解决的。
- 优先用同类型系统字体:Inter / Roboto →
system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI' - 中文场景慎用
'PingFang SC'fallback 到'Noto Sans CJK SC',两者字宽接近但 baseline 偏移约 8%,需单独测ascent-override - 关键区域(如导航栏文字)可加
contain: layout paint,把重排影响限制在局部,避免整页跳
最易被忽略的是:override 值不是一劳永逸的——换字体版本、换字号、甚至换用户系统字体配置,都可能让原先调好的百分比失效。上线前必须在真实设备 + 无缓存模式下测首屏文字区域的 layout shift 分数。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











