font-display: swap单独使用仍抖动,是因为未配合preload(需crossorigin/as="font")、字体度量对齐(size-adjust/ascent-override)、同类型fallback链及woff2 format声明,导致替换时行高、x-height等差异引发cls。

字体和图片加载导致的页面闪烁(FOIT/FOUT/CLS),本质是浏览器在等资源就绪时反复重排重绘。直接加 font-display: swap 或 loading="lazy" 不够——必须配合关键样式预加载,才能切断重排链。
为什么只设 font-display 还会抖动
即使写了 font-display: swap,如果字体文件本身没提前下载,浏览器仍要等网络响应才触发替换,期间备用字体撑开的高度可能和最终字体不一致,造成行高跳变、按钮错位、导航栏塌陷。
- 没
<link rel="preload">时,字体请求通常在 CSS 解析完才发起,晚于首屏渲染 -
crossorigin缺失会导致 preload 失效(哪怕字体同源),Network 面板里看不到 high 优先级请求 - WOFF2 文件若返回错误的
Content-Type: font/woff2,部分浏览器会静默丢弃,不报错但字体永不加载
图片重排必须预设宽高 + preload 关键图
没设 width 和 height 的 <img> 加载后必然触发重排;而首屏大图(如 banner、logo)若靠 loading="lazy" 延迟加载,用户看到的就是空白或占位符闪进——这不是懒加载的问题,是它不该用在首屏。
- 首屏
<img>必须显式写width和height(可用 CSS aspect-ratio 替代,但需兼容性兜底) - 关键图(如 logo、首屏主图)要用
<link rel="preload" as="image">提前拉取,别等 HTML 解析到才发起请求 -
<picture></picture>中的<source></source>不会触发 preload,必须对最终 fallback 的<img src>单独 preload
critical CSS 内联 + 字体 preload 要同步生效
内联 critical CSS 只解决样式阻塞,不解决字体和图片资源延迟。如果 critical CSS 里用了自定义字体,但字体还没开始下载,浏览器依然得等——此时文本要么白屏(FOIT),要么用系统字体撑开再跳(FOUT)。
- preload 字体的
href必须和@font-face中的src完全一致(包括路径、查询参数) - critical CSS 应该包含所有首屏文字的
font-family声明,且对应字体已通过 preload 启动下载 - 不要把非首屏用的字体也 preload,会抢占带宽,反而拖慢真正关键的资源
真正卡点不在“有没有加 swap 或 lazy”,而在“关键资源是否在 HTML 解析第一毫秒就开始下载”。漏掉 crossorigin、写错 as 类型、或者让首屏图走懒加载,都会让预设失效。这些细节不验证,优化就停在表面。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











