transition必须写在img元素自身上,且初始opacity需显式设为0;配合load事件触发show类实现可靠淡入,再结合aspect-ratio和object-fit保障响应式图片布局。

transition 必须写在 img 元素自身上,不能只写在父容器
很多人写了 transition: opacity 0.6s 却没效果,第一反应是“CSS 没生效”,其实大概率是把它加在了 .image-wrapper 这类父容器上。opacity 是作用在 img 上的,transition 就必须也写在 img 上——浏览器不会“继承”过渡行为。
常见错误写法:.image-wrapper { transition: opacity 0.6s; }img { opacity: 0; }
这样切换 img 的 opacity 时,依然瞬时变化。
正确做法是:img { opacity: 0; transition: opacity 0.6s ease-out; }
再配合 JS 切换类或直接改 style.opacity,动画才能触发。
初始 opacity 值必须显式声明,不能靠继承或默认
HTML 中 img 默认 opacity 是 1,但如果你希望它“一上来就淡入”,就必须手动设为 0,并确保这个值在渲染前已存在——否则页面加载时会先闪一下全不透明,再开始动画。
推荐用内联样式或初始类控制:<img src="a.jpg" class="fade-in" style="opacity: 0;">
或 CSS 中写:.fade-in { opacity: 0; transition: opacity 0.6s ease-out; }
注意:
- 不要写 opacity: 0%,只接受 0–1 的数字
- 不要用 visibility: hidden 或 display: none 配合 opacity,它们会让 transition 中断
- 如果图片是懒加载的,需等 load 事件后再加 show 类,否则可能在未加载完时就触发淡入
响应式场景下,aspect-ratio 比固定宽高更可靠
纯靠 width: 100% + height: 300px 在不同屏幕下容易拉伸或留白。现代方案优先用 aspect-ratio: 16/9(或你实际需要的比例),让容器自动维持比例,图片再用 object-fit: cover 填满。
示例结构:<div class="img-container"><img src="x.jpg" class="fade-in"></div>
对应 CSS:
.img-container { aspect-ratio: 16/9; width: 100%; max-width: 800px; margin: 0 auto; }<br>
.img-container img { width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 0.5s ease-in-out; }
这样在手机、平板、桌面端都能保持一致视觉节奏,且无需媒体查询干预。
立即学习“前端免费学习笔记(深入)”;
JS 触发淡入时,别直接改 display 或跳过 load 状态
如果图片是动态插入或 src 后续才设置,直接设 opacity: 1 很可能在图片还没加载完成时就执行,导致“淡入一张空白”。
稳妥做法是监听 load 事件:img.addEventListener('load', () => { img.classList.add('show'); });
配合 CSS:.show { opacity: 1; }
还要考虑失败情况:
- 加个 onerror 回退逻辑,比如显示占位图或文字提示
- 若用 srcset 或 picture,确保所有源都触发 load(实际只触发一次)
- 不要用 setTimeout 猜加载时间,网络波动下极不可靠
最易被忽略的一点:opacity 动画本身不解决图片加载延迟,它只是把“出现”这个动作变柔和。真正影响体验的是资源加载时机和 fallback 设计——比如用低质量占位图(LQIP)先撑住布局,再淡入高清图,这比单纯调 opacity 更接近用户感知的真实“渐变”。



















