换成本地字体后加了 size-adjust 做回退匹配,CLS 从 0.02 涨到 0.24。字段数据里九成的不稳定来自首屏标题的文字跳动。
一开始怀疑是「回退字体与正文字体的 ascent、descent 差异过大」,查了一圈,方向不对。
真正麻烦的地方在于,几个原因的现象几乎一样。size-adjust 的值是按字符宽度估的,行高没跟着调。也可能是font-display 用了 block,首屏文字延迟渲染导致整体位移。
还有一种情况,标题用了 rem 定高,字体换掉后行盒高度变化。
量两种字体的度量差异
fc-scan --format '%{family} %{ascent} %{descent}\n' /usr/share/fonts/noto.otf
接着按度量值调整 size-adjust 与 ascent-override
@font-face{font-family:fallback;src:local('Noto Sans CJK SC');size-adjust:98%;ascent-override:88%;}
再往下把 font-display 改成 swap
font-display: swap;
等前面都确认过,再用布局偏移观察器定位跳动元素
new PerformanceObserver(l=>l.getEntries().forEach(e=>console.log(e.sources))).observe({type:'layout-shift',buffered:true})
我习惯把每一步的执行时间和结果记在一边,后面复盘省事。
改完先别撤,确认这几项。首屏标题不再跳动,CLS 从 0.24 回落到 0.01 左右,字段数据在两周后同步改善。
提醒一点。换字体引起的 CLS 往往被忽略,度量覆盖参数要比肉眼调更准,ascent 与 descent 两个值一起对。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
