对 img 的 src 属性加 transition 无效,因其不可动画;应通过 opacity 或 transform 实现过渡,配合 onload 等待加载完成,避免闪烁。

直接给 <img> 标签加 transition 对 src 属性无效——浏览器不支持对 src 做动画,硬加只会白费力气。
为什么不能对 src 写 transition
src 是一个“非可动画属性”,CSS 的 transition 只能作用于可计算、有中间值的属性(比如 opacity、transform、width)。图片切换时的空白/闪烁,本质是加载间隙 + 渲染时序问题,不是样式跳变。
- 常见错误现象:
transition: all 0.3s或transition: src 0.3s—— 完全没效果,控制台也不会报错,纯属静默失效 - 真正起作用的过渡目标只有两个:视觉可见性(
opacity)或位置(transform) - 若用
display: none/block切换,同样无法过渡——display没有中间态,transition对它无效
用 opacity + class 切换实现淡入淡出
这是最轻量、兼容性最好、也最容易调试的方案。核心是让旧图渐隐、新图渐显,中间靠 JS 控制时机,避开加载空白。
- 给图片容器(如
<div class="image-list">)或每个<img>加transition: opacity 0.4s ease-out - 定义两个类:
.hidden { opacity: 0 }和.visible { opacity: 1 }(后者可省略,因默认就是 1) - 切换时分三步:
element.classList.add('hidden')→setTimeout(() => { 更新 src; element.classList.remove('hidden').add('visible') }, 400) - 注意:必须等
hidden类生效并触发过渡后,再改src,否则新图可能在旧图还没消失前就闪现
用 transform 实现滑入滑出(适合横向轮播列表)
如果图片是排成一行的轮播结构(比如 <div class="slides"> 包着多个 <img>),优先用 transform: translateX(),而不是 left 或 margin-left。
立即学习“前端免费学习笔记(深入)”;
-
left或margin触发重排(reflow),容易卡顿;transform走合成层,GPU 加速,顺滑得多 - 结构建议:
.slides { display: flex; transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) } - 每次切换只需更新
.slides.style.transform = 'translateX(-' + offset + 'px)',动画自动触发 - 别忘了设
.slides { will-change: transform }(可选,对长列表有轻微性能提升)
容易被忽略的加载与事件时机问题
过渡效果“看起来卡住”或“闪一下”,大概率不是 CSS 写错了,而是 JS 没等图片加载完成就强行显示。
- 新图
src更新后,应监听img.onload再执行remove('hidden'),否则可能在图还没解码完时就透明度归 1,出现白块 - 移动端快速连点切换按钮时,要防重复触发:加个
isTransitioning标志位,setTimeout结束后再置为false - 如果列表里图片尺寸差异大,记得统一设
object-fit: cover和固定宽高,否则transform位移会因容器跳动而失准



















