CLS 是什么?常见布局偏移应该如何优化?
简化版
CLS 衡量页面生命周期内非预期布局偏移的累积分数,良好标准是 P75 不超过 0.1。优化重点是为图片、视频、广告、异步内容和字体预留空间,避免在已有内容上方插入元素,并避免用会触发布局的动画属性。
详细版
布局偏移发生在可见元素从上一帧位置移动到下一帧位置时。用户主动操作后的合理变化通常不计为意外偏移,但页面自动加载图片、广告、字体替换或异步模块导致内容下跳,会影响 CLS。
常见手段包括设置图片和 iframe 的 width/height 或 aspect-ratio,广告位用固定容器占位,骨架屏尺寸接近真实内容,字体用合理 font-display 和尺寸兼容的 fallback,动画优先 transform 而不是 top/height。
回答时要强调 CLS 是现场指标,SPA 的后续路由和延迟插入也可能累计;不能只靠首屏 Lighthouse 一次分数判断。
完整版教学
一、CLS 衡量的是视觉稳定性
页面加载时,用户正准备点击“确认”,按钮突然被上方插入的广告挤下去,这类体验比慢还糟。CLS 用来衡量非预期布局移动造成的稳定性问题。
当前良好阈值是 CLS ≤0.1,>0.25 为差,评价同样看真实访问 P75。它不是毫秒,而是无单位分数,来自偏移影响范围和移动距离。
记忆钩子:CLS 关心的不是“变了没有”,而是“用户没预期时,屏幕内容被挪了多少”。
二、布局偏移分数怎么理解
一次布局偏移大致由影响比例和距离比例相乘得到。影响比例表示被影响元素覆盖了多少视口,距离比例表示移动距离占视口多少。
layout shift score = impact fraction × distance fraction
假设一个卡片区域影响 50% 视口高度,并向下移动 20% 视口高度,则该次分数约 0.5 × 0.2 = 0.1。一次看似普通的图片撑开,就可能把页面推到需要改进边界。
实际浏览器还会按会话窗口聚合偏移。面试不用死背所有细则,但要知道 CLS 是累计视觉稳定性指标,不是单个元素的像素距离。
三、图片、视频和 iframe 要预留尺寸
最常见的 CLS 是媒体资源晚加载后撑开容器。浏览器如果不知道资源尺寸,只能先按零高度或临时高度布局,资源到达后再重排。
<img
src="/cover.avif"
width="800"
height="450"
alt="课程封面"
/>
现代浏览器可根据 width 和 height 推导宽高比,响应式缩放时仍能预留高度。CSS 中也可以用 aspect-ratio: 16 / 9。关键是让布局在资源下载前就知道它占多大空间。
四、广告、推荐位和异步内容要占坑
广告和推荐模块经常由异步脚本插入,如果直接插到正文上方,会把后续内容全部推下去。正确做法是提前给容器固定或最小高度。
| 模块 | 常见问题 | 优化方式 |
|---|---|---|
| 广告位 | 脚本晚到撑开 | 固定容器、空广告也保留空间 |
| 推荐列表 | 接口回来插入 | 骨架屏与真实高度接近 |
| Cookie 横幅 | 顶部突然出现 | 底部覆盖或首屏预留 |
| A/B 实验 | 客户端改布局 | 服务端分流或预留变化区域 |
假设首屏正文顶部插入 120px 广告,移动端视口高 800px,主要内容都被推下 15% 视口。如果受影响区域很大,CLS 会非常明显。
五、字体也会造成布局偏移
Web Font 加载前后,fallback 字体和目标字体的字宽、行高不同,文本可能换行或按钮宽度变化。字体问题常被忽略,因为它不是资源“撑开”,而是字形替换导致布局变化。
可以用 font-display 控制字体显示策略,选择尺寸接近的 fallback,必要时用字体度量覆盖让 fallback 更接近目标字体。品牌字体不要无脑阻塞首屏文本。
@font-face {
font-family: "Brand";
src: url("/brand.woff2") format("woff2");
font-display: swap;
}
swap 能减少不可见文本时间,但可能带来字体替换瞬间变化;optional 更保守,弱网下可能直接使用 fallback。选择要结合品牌要求和 CLS 数据。
六、动画和交互变化要区分预期与非预期
用户点击展开面板后内容移动,通常属于预期变化;页面自己突然插入内容,则更可能计入 CLS。即便如此,交互动画也应尽量平滑,避免用户误触。
布局属性动画如 height、top、margin 可能触发布局;视觉移动可以优先用 transform,让元素在合成阶段变化,减少对其他元素位置的影响。
.toast {
transform: translateY(0);
transition: transform 180ms ease;
}
如果需要真实展开占位,也应在交互发生后立即开始,并避免延迟超过用户预期窗口。用户点了按钮 2 秒后才移动内容,会显得像意外偏移。
七、常见误区与追问
- 误区:CLS 只发生在页面加载阶段。 SPA 路由切换、懒加载模块、广告刷新和长会话异步插入都可能产生偏移。
- 误区:图片已经压缩就不会影响 CLS。 压缩只减少下载时间,不预留尺寸仍会晚到撑开。
- 误区:所有字体 swap 都最好。 swap 改善可见性,但字体替换可能带来文本重排和偏移。
- 追问:为什么广告位空了也要保留空间? 移除占位会让页面上移,同样可能造成视觉不稳定。
- 追问:如何定位 CLS 来源? 用 DevTools Layout Shifts、PerformanceObserver 或 RUM 上报偏移元素信息。
- 追问:transform 为什么更适合动画? 它通常不改变文档流中其他元素布局,减少布局偏移和重排。
八、加强记忆
CLS 按“先占位、少插入、稳字体、慎动画”记:媒体和异步模块提前给尺寸,广告和推荐位不要凭空挤压正文,字体策略要兼顾可见性和尺寸稳定,动画优先不影响布局的属性。最终看真实用户 P75 和偏移来源,而不是只看本地首屏。