仅设 max-width: 100% 会导致图片加载前高度为0,内容突然下移;应优先用 aspect-ratio 占位,配合内联宽高或 JS 动态注入,fallback 用 ::before + padding-top,并确保容器 position: relative 且有明确宽度。

为什么只写 max-width: 100% 会导致布局抖动
图片加载前高度为 0,浏览器无法推算宽高比,等图片资源返回才撑开容器——内容往下“掉”,用户正在读文字,突然跳一下。这不是动画卡顿,是布局缺失导致的视觉断裂。关键不是“怎么动”,而是“怎么先占住位置”。
aspect-ratio 是首选,但必须配合内联宽高或 JS 动态注入
现代方案直接用 aspect-ratio: 16 / 9,但 Safari 15.4 之前不支持,且仅靠 CSS 声明无法应对后端返回比例不固定的图片。
- 服务端/构建时已知比例 → 直接写内联
style="aspect-ratio: 16 / 9",再加@supports (aspect-ratio: 1/1)做降级 - 响应式图片(
srcset)必须保留内联width和height属性,否则 Chrome/Safari 会忽略宽高比推算 - 后端图比例不可控 → 用 JS 读取原始尺寸后动态设 CSS 变量:
img.style.setProperty('--aspect-ratio', w/h),再在 CSS 中用aspect-ratio: var(--aspect-ratio)
纯前端 fallback:用 ::before + padding-top 占位要避开三个坑
经典 padding hack 在移动端仍有效,但容易因单位、定位或父容器干扰失效。
- 必须给容器设
position: relative,否则伪元素无法绝对定位盖住图片 -
padding-top百分比基于父容器宽度计算,所以父容器必须有明确宽度(比如width: 100%或 flex item 的固有宽度) - 不要在伪元素里写
background-image,它会触发额外请求;用纯色或渐变模拟加载态更轻量
懒加载触发后,如何避免图片“从 0×0 突然放大”
直接对 img 加 opacity 或 transform 动画会失败,因为加载完成前自然尺寸是 0×0,动画起点失真。
立即学习“前端免费学习笔记(深入)”;
- 正确做法:用伪元素做加载层,真实
img初始opacity: 0,加载完成加.loaded类触发动画 -
img必须有确定的宽高比容器(aspect-ratio或 padding hack),否则动画过程中容器还在变化 - IntersectionObserver 回调里应立即赋值
src,并在img.onload后再加类,避免未加载完就动效
aspect-ratio 或 padding,首屏已经闪过了。


















