你正在读,一张图片加载完成,整个页面往下一跳。这就是累积布局偏移(CLS),而图片是它最常见的成因。

为什么会发生

HTML 是边到达边排版的。当浏览器遇到一张不知道尺寸的图片时,它会预留零高度,把下方文字先排好,直到图片数据到达才发现真实尺寸——于是下面的一切被迫移动。

解法:把尺寸告诉浏览器

给每个 img 元素写上 width 和 height 属性,值为图片的原始像素尺寸。现代浏览器会由这两个数字算出宽高比,即使你的 CSS 让图片是流式的,也能预留出比例正确的空间。

这里正是大家搞错的地方:给一张设置了 width: 100% 的图片写 width="1600" height="900",感觉很矛盾。其实不矛盾。属性提供的是*比例*,CSS 仍然控制实际渲染尺寸。两者都需要,再加上把 height 设为 auto 的标准响应式规则,图片才不会变形。

当你确实不知道尺寸时

有时尺寸在运行时之前真的未知——用户上传、CMS 内容、第三方数据源。可选方案:

  • 在容器上用 CSS 设置 aspect-ratio,配合 object-fit 裁切。无论来的是什么,空间都已预留。
  • 在上传时把尺寸存进 CMS,输出到标记里。对任何内容驱动的站点,这是最稳健的方案。
  • 装饰性图片可以用固定高度容器加 overflow hidden。

其他与图片相关的偏移

  • Web 字体替换会让图片周围的文字移动;用能减少重排的 font-display 设置。
  • 后插入的横幅、Cookie 提示和广告若位于内容上方,会把一切下推——它们的空间也要预留。
  • 没有尺寸的懒加载图片会在滚动时持续偏移,这与首屏偏移一样计入分数。
  • 各断点比例不同的响应式图片需要为每个断点设置对应的宽高比,否则在某些宽度下偏移会回来。

验证是否修好

  • Lighthouse 会报告 CLS 并指出发生偏移的元素。
  • DevTools 的 Rendering 面板有"Layout Shift Regions"叠加层,能在偏移发生时高亮显示。
  • 在限速网络下测试:高速 WiFi 下图片在布局重要之前就到了,恰恰会掩盖你想观察的问题。

关于占位图

纯色块、模糊的低质量预览图和骨架屏都能改善*感知*性能,但只有当它们占据的正是最终尺寸时,才真正解决 CLS。尺寸不对的占位图照样会跳。先把预留空间做对,再考虑好不好看。