现场是这样的。全站字体改成自托管后 font-display 用 swap,移动端 CLS 从 0.02 涨到 0.14,首屏标题在字体加载完成时整体跳行,广告位的位置没有变化。

中间走过弯路,把「标题用 vw 字号,字体切换后换行位置改变」当成主因,改完现象没变。

把日志和配置对完,能解释这个现象的基本就这几处。自托管字体的度量与系统回退字体差异大,swap 后行高变化;回退字体没有设置 size-adjust,字形宽度不同;关键字体没有 preload,加载时机晚于首屏绘制。

第一件事是看字体声明里的 display 策略

curl -s https://www.example.com/ | grep -o 'font-display:[a-z]*'

给回退字体加度量修正

@font-face { font-family: Fallback; size-adjust: 107%; ascent-override: 92%; }

再往下关键字体加 preload

grep -n 'preload' templates/layout.html

末了改动后重新取 CLS 数据

curl -s 'https://crux.example.com/api?origin=https://www.example.com'

恢复的判定其实很直接。CLS 回落到 0.05 以内,首屏标题的换行位置与系统字体一致,字体加载完成时不再位移。

提醒一点。swap 能避免文字不可见,但会把位移暴露出来,度量修正和 preload 要一起做才有效。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189