你点开自己写的页面,正想读第一段,结果文字“唰”一下往下跳——配图还没出来,按钮已经滑出屏幕了。不是网卡,不是手抖,是页面在你眼皮底下偷偷改版。
这感觉谁没经历过?CLS 就是那个总在关键时刻捣乱的隐形 Bug。
为什么图片加载完总让你的页面“抖一下”?
浏览器看到 <img> 标签时,如果没写 width 和 height,它根本不知道这张图要占多大地方。等图一加载完,“砰”地塞进来,后面所有内容全被往下顶。
响应式图片更狡猾。你写了 width: 100%,但没管高度,手机上图被压成方块,标题直接被挤走。用户刚扫到第三行字,图一到位,视线瞬间断掉。
解决办法很简单:每张图都补上 width 和 height 属性。
如果是现代项目,CSS 里加一句 img { aspect-ratio: 16/9; width: 100%; height: auto; } 就够了。浏览器提前知道比例,留好位置,图再慢,页面也不晃。
字体加载导致的布局偏移怎么彻底解决?
字体文件大、加载慢,浏览器只能先用系统字体撑着。等自定义字体一落地,每个字的宽高重算,整段文字“缩”或“胀”,连带周围元素一起位移。
有家知识付费站首页用了三套字体,每次打开,标题、正文、按钮轮流跳,用户说:“像在看PPT翻页。”
别硬扛。两个实用方案:
- 关键位置(比如 Logo、主标题)用
font-display: block,宁可等一会儿,也要留足空间; - 正文、说明文字这类非视觉焦点,直接上
font-display: optional,100ms 内没加载成功就放弃,全程用系统字体——不美,但稳。
顺手把字体 <link rel="preload"> 也加上,让它抢在 HTML 解析完就开下。
动态插入内容时,如何避免页面“跳楼式”偏移?
广告、推荐栏、评论区、弹窗……这些内容不是一开始就有的。它们在 DOM 里突然冒出来,就像有人在你读到最后一句时,猛地往你脚底下塞了块砖——页面“咚”一下沉下去。
最典型的是广告。你预留了 300×250 的坑位,广告返回个 300×600 的横幅,整个版面直接变形。更糟的是,有些广告等你滚动到一半才加载,正文当场被掀翻。
做法很实在:
- 所有异步内容,先用一个固定尺寸的容器占位。尺寸不确定?至少设个
min-height,别让它空着塌掉; - 广告容器加
overflow: hidden或max-height,超出部分裁掉,不许它乱伸腿; - 评论区这类长内容,初始状态用骨架屏占位,高度和最终内容一致,数据来了再填进去。
还有 Cookie 弹窗——别让它等页面渲染完再蹦出来。要么 position: fixed 脱离文档流,要么在 <body> 顶部预留一块固定高度区域,让它有地儿落。
滚动条的出现和消失,为什么会引发连锁位移?
很多人完全没意识到这事有多烦人。
列表页内容少,没滚动条;点进详情页,内容一长,滚动条“啪”地弹出来,占掉 17px 宽度。所有文字块被迫重排,换行点变了,图片被挤扁,布局跟着晃。
页面切换时这种抖动最隐蔽,用户可能没察觉,但 CLS 分数已经爆表。
解法就一行 CSS:
html { overflow-y: scroll; }
强制滚动条常驻。宽度恒定,布局就不会被它反复拿捏。
交互动画和过渡效果,如何避免产生CLS?
注意:用户点下去之后 500ms 内发生的动画,浏览器默认不计入 CLS。这是你的安全窗口。
但很多“自动动画”卡在灰色地带。比如滚动到某处,侧边栏自动滑出;或者定时器一到,通知框弹上来——这些没人点,浏览器照记不误。
正确姿势是:所有非交互触发的动效,只用 transform 和 opacity。
- 想让元素滑入?写
transform: translateY(-20px)→transform: translateY(0),别碰top或margin-top; - 想淡入?只调
opacity,别改visibility或display。
这两个属性不触发布局重排,再炫的动效,CLS 也纹丝不动。
今天就能执行的3个CLS修复动作
别等“大版本优化”。现在打开电脑,花 15 分钟,立刻见效。
打开 Chrome DevTools → Lighthouse → 点“生成报告”。选中“Performance”,跑一次。报告里会标出所有 Layout Shift 区域,重点看图片、广告位、字体加载前后。截图存好,这就是你今天的靶子。
打开你网站任意一个文章页的源码(右键 → 查看页面源代码),搜
<img,挨个检查有没有漏掉width和height。没有的,补上;响应式图,在 CSS 里给img加上aspect-ratio。打开 Chrome DevTools → Elements 面板,展开
<body>,滚动页面,观察哪些区块是后来插入的(比如#ad-banner、.related-posts、.cookie-banner)。找到它们的父容器,在 CSS 里给它加个min-height: 200px(数值按实际预估),确保它始终占位。
做完这三步,你页面的“抽搐感”会明显缓解。字体和滚动条的问题可以放明天下午茶时间顺手处理。CLS 不是玄学,就是一个个具体元素的位置管理——你盯住它们,它们就不敢乱动。