平滑图片过渡只有叠层opacity切换或transform:translatex()滑动两类方案;直接改img.src会闪屏因加载与视觉时序失控,须等load事件或延时后再显新图。

直接改 img.src 会闪白或黑屏,不是浏览器“不支持动画”,而是你没控制好加载与视觉状态的时序。真正能落地的平滑过渡只有两类方案:叠层 opacity 切换,或用 transform: translateX() 移动容器——选错路径,动画就断在中间。
为什么直接改 src + transition: opacity 会闪
常见错误是这样写 CSS:
.slider-img { opacity: 1; transition: opacity 0.4s; }
然后 JS 里直接执行 el.src = nextSrc。问题在于:浏览器一改 src,立刻清空当前图像内容(变成透明/空白),此时 opacity 开始从 1 往 0 走,但新图还没加载完,用户看到的就是“空帧”。
- 过渡必须限定为
opacity,不能写transition: all 0.4s,否则可能意外触发布局重算 -
src更新后,得等load事件触发,或至少延迟等于 CSS 过渡时长(如 0.4s),再把新图设为可见,否则淡入时图还是空的 - 不要用
display: none替代opacity: 0,它会中断过渡、且无法触发transition
用绝对定位叠层 + class 切换实现淡入淡出
这是最轻量、兼容性最好、也最容易调试的方式。所有图片放在同一位置,靠 opacity 和 z-index 控制显隐顺序。
- HTML 结构:多个
<img>并列,父容器设position: relative - CSS 中每张图设
position: absolute; top: 0; left: 0; opacity: 0; transition: opacity 0.5s ease-in-out - 当前显示图加
.active类,对应opacity: 1;其他图保持opacity: 0 - JS 切换逻辑:先移除所有
.active,给下一张加.active——浏览器自动触发opacity过渡
用 transform: translateX() 实现滑动轮播
要做左右滑动效果(比如手机端轮播),千万别用 left 或 margin-left 动画——它们强制浏览器每帧重排布局,低端机上明显卡顿。
- 把所有图片包进一个
<div class="slides">,设 <code>display: flex或white-space: nowrap -
.slides自身设transform: translateX(-300px)(假设每张宽 300px),过渡只加在该容器上:transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) - 每次切换只更新
.slides的transform值,不操作单个img元素 - 务必确保父容器有固定宽高和
overflow: hidden,否则滑动会溢出 - 统一用
transform: scale()和transform: translateX()等合成属性 - CSS 必须写
transition: transform 0.3s ease,不能漏掉transform明确指定 - 图片放大时容易撑开容器,建议套一层固定尺寸的
<div class="img-container"> 并设 <code>overflow: hidden - 移动端可加
transform: translateZ(0)启用 GPU 加速,但注意部分安卓 WebView 对此支持不稳定
图片缩放/位移类过渡要避开宽高直改
想让图片 hover 时放大,或点击后移动位置,别碰 width/height/top/left ——这些属性会触发重排,动画掉帧。
最容易被忽略的是:所有基于 transform 或 opacity 的过渡,都依赖元素始终在文档流中存在。一旦你用 JS 把某张图 removeChild 或设 display: none,动画链就彻底断了——这不是 bug,是机制使然。











