必须在html源码中显式声明width和height,否则浏览器无法首帧预留空间导致抖动;img、iframe、广告位、svg、video等均需硬编码尺寸或占位,css无法替代。

必须在 HTML 源码中显式声明 width 和 height,否则浏览器无法在首帧渲染前预留空间——这是抖动的根源,不是 CSS 能补救的。
img 和 iframe 必须带 width/height 属性,CSS 无效
浏览器解析 HTML 时,<img> 或 <iframe></iframe> 缺少 width 和 height,就按 0×0 或行内默认尺寸占位。等资源加载完成才重排,下方文字/按钮全被顶下去。
-
<img src="a.jpg">→ 抖动高发;<img src="a.jpg" style="max-width:90%" style="max-width:90%">→ 首帧即知尺寸,稳 - 只写
width不写height,Chrome 99+ 可能无法准确推算宽高比,仍触发轻微重排 -
max-width: 100%、aspect-ratio: 16/9是补救,不是替代;旧版 Safari 首帧仍可能 fallback 到无占位状态 -
srcset+sizes场景下仍要配width/height,否则浏览器可能先按默认尺寸占位再调整,造成两次偏移
广告/评论等动态内容注入前必须硬占位
JS 插入模块(如广告、推荐、评论)时,若父容器无明确高度约束,插入瞬间就会挤压流内元素——Lighthouse 常标为 贡献 CLS,实际就是这类元素在作祟。
- 在 HTML 源码中就写好占位:
<div id="ad-slot" style="min-height: 250px"></div>,高度尽量接近历史均值 - 避免用
visibility: hidden或opacity: 0占位——它们不脱离文档流,但无尺寸,等于没占 - 骨架屏比纯空容器更优:提供视觉预期,且自身结构稳定,不依赖内容尺寸
- 第三方组件(如 cookie banner)优先用
position: fixed或position: sticky,彻底脱离文档流
模态框开启时 body 宽度突变必须用 margin-right 补滚动条宽度
模态框一开,body 滚动条消失,页面可用宽度瞬间增大,右侧内容左移——这不是样式问题,是结构级宽度重计算。
- 仅靠
overflow: hidden简单禁用滚动条,只会让抖动更明显 - 正确做法:先读
document.body.offsetWidth,设document.body.style.overflow = 'hidden',再读一次,差值就是滚动条宽度 - 用
document.body.style.marginRight = '${scrollBarWidth}px'锁住宽度 - 关闭模态框时,记得清掉
marginRight和overflow
SVG 和 video 的占位容易被忽略
SVG 不写 viewBox,旧版 Safari 可能 fallback 到 300×150 默认渲染再缩放;<video></video> hover 移位本质是盒模型突变,不是 :hover 本身的问题。
- SVG 必须带
viewBox,且显式设width/height,否则某些场景会按 300×150 渲染再缩放 -
.video-container:hover video { border: 2px solid #007bff; }→ 初始无边框,hover 加 2px 实色边框,宽度+4px,必然跳 - 正确做法:初始用
border: 2px solid transparent占位,hover 只改border-color -
<video></video>必须设display: block,避免行内换行间隙干扰;父容器需有明确宽高或至少设min-height
真正难的不是加几个属性,而是所有占位都要在 HTML 源码里“提前写死”——JS 注入、懒加载、响应式图片、第三方脚本,每个环节都可能绕过你的 CSS 控制。抖动不是渲染 bug,是 HTML 没给浏览器足够确定性信息。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











