CLS(Cumulative Layout Shift)是量化页面视觉稳定性的指标,数值越大表示非用户触发的意外布局位移越严重,如图片缺宽高、字体加载替换、广告占位不足等导致内容跳动。

CLS 是什么,为什么它直接暴露布局抖动
CLS(Cumulative Layout Shift)不是个“性能分数”,而是对页面视觉稳定性的量化测量——数值越大,说明用户看到的内容越容易突然位移。它不关心加载快慢,只记录元素在渲染完成后的意外移动。只要一个按钮在用户准备点击时向下跳了 20px,或者图片加载后把下方文字顶下去,CLS 就会记一笔。
关键点在于:CLS 只统计「非预期的、非用户触发的」位移。比如滚动中动态插入内容、字体加载替换、广告占位不足、图片缺 width/height,都会被计入。
常见错误现象:
- 页面首屏加载后,文字或按钮“跳一下”才停稳
- 点击弹窗后,背景内容向上/向下偏移
- 第三方广告或嵌入 iframe 加载完成,导致整个视口重排
用 Chrome DevTools 实时定位抖动源
别等 Lighthouse 报告——打开 DevTools → Performance 标签页 → 点击录制(●),然后刷新页面并模拟用户操作(如滚动、点击)。停止后,在底部 Summary 面板切换到 Layout Shifts 子标签。
这里每一条红条都对应一次位移事件,点击后右侧会显示:
-
shifted elements:具体哪个 DOM 节点发生了位移(注意看是否是<img>、<iframe>或第三方容器) -
impact region:位移影响的像素区域大小(越大越危险) -
distance fraction:位移距离占视口比例(>0.002 就可能被计入 CLS)
特别注意:如果位移源是内联样式或 JS 动态插入的节点,DevTools 会标出触发它的 JS 调用栈,这时候直接跳转到 sources 定位问题代码行。
图片、字体、广告这三类最常拉高 CLS 的场景怎么修
它们共性是“资源异步加载 + 缺乏占位预估”,修复逻辑一致:让浏览器提前知道尺寸或渲染边界。
-
图片:必须设
width和height属性(不是 CSS),否则现代浏览器无法预留空间;用loading="lazy"时更要确保尺寸存在,否则懒加载触发时仍会抖 -
字体:用
@font-face的font-display: optional或swap时,要搭配size-adjust或 fallback 字体行高一致;避免用 JS 动态注入@font-face -
广告/嵌入内容:禁止用
height: auto或min-height占位;改用固定宽高容器 +aspect-ratio(支持较新浏览器)或 padding-bottom hack;第三方脚本加载前先渲染带data-ad-status="loading"的占位 div
示例(安全的广告占位):
<div style="position: relative; width: 100%; aspect-ratio: 4 / 1"> <div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%" data-ad-status="loading"></div> </div>
CLS 不是越低越好,但超过 0.1 就得立刻干预
Google 把 CLS document.write() 插入的广告脚本在 iOS Safari 上造成 0.3 的单次抖动。
真正要盯住的是:每次位移是否可归因、是否可复现、是否发生在用户关键路径上。比如支付页按钮跳动一次,比首页 banner 晃三次更紧急。
容易被忽略的一点:CLS 在真实设备上往往比桌面 DevTools 高,尤其低端 Android 机型加载 WebFont 或图片解码慢,位移延迟更明显。别只信本地测试数据。

















