最稳方案是用display: none切换图片,外层用包平级,每图设宽高和alt,切换时先隐藏全部再显示当前,轮播需clearinterval防并发,容器设固定高度防塌陷。

直接用 display: none 切换图片最稳,别一上来就搞 transform 动画或 opacity 过渡——先让“只显示一张图”这件事不翻车,再谈效果。
用 <div class="carousel"> 包所有图,别塞进 <code><ul></ul> 或 <picture></picture>
容器必须是独立的 <div>,里面直接放 <code><img> 标签,每张图带 alt 和固定宽高(比如 width="600" style="max-width:90%")。常见错误是把多张图塞进一个 src 属性里,或者用 <ul><li><img></li></ul> 套着写——src 只认单 URL,<ul></ul> 会引入无意义的列表语义和默认 margin,干扰定位。
实操建议:
- 外层写
<div class="carousel">,方便后续加 JS 选择器和 CSS 控制 <li>图全部平级放在里面:<code><img src="a.jpg" alt="A" style="max-width:90%" style="max-width:90%">,不嵌套、不懒加载、不srcset - 避免用
<figure></figure>或<picture></picture>开头——响应式和语义化是第二步,先跑通逻辑 - JS 里用
document.querySelectorAll('.carousel img')拿到全部图 - 每次
showImage(index)前,遍历设el.style.display = 'none' - 再设目标图
imgs[index].style.display = 'block' - 别用
visibility: hidden——它占位,可能撑开容器高度;也别用opacity: 0——仍响应点击,且动画要额外配transition - 定义全局变量
var carouselTimer = null - 每次启动前先
clearInterval(carouselTimer),再carouselTimer = setInterval(...) - 给
.carousel绑mouseenter(暂停)和mouseleave(恢复),左右按钮点击后也要调resetTimer() - 别用
setTimeout递归模拟——容易堆栈溢出,且不好统一清理 - 给
.carousel设死高度,比如height: 400px,不依赖图片撑开 - 加
onerror回调兜底:<img src="x.jpg" onerror="this.style.display='none'"> - 避免用 SVG 当 fallback 图——部分老浏览器解析 SVG 失败会白屏,用 PNG 更稳妥
- 如果图来自 CDN,检查是否开了 CORS,否则
onerror可能不触发
display: none 切图时,顺序不能反
所有 <img> 默认设 style="max-width:90%",第一张手动加 display: block。切换时必须「先清空所有,再设当前」,否则残留图会叠在上面。
常见错误现象:点第2张,第1张还半透明挂着;切到第3张,第2张边角露出来。
实操建议:
自动轮播必须配 clearInterval + 暂停逻辑
只写 setInterval(switchImage, 3000) 是危险操作:鼠标悬停还在切、点按钮后定时器没停、页面切走再回来可能多个定时器并发运行。
性能与兼容性影响:移动端没有 mouseenter,但 touchstart 可补;IE 不支持 let,变量声明得用 var。
实操建议:
图片加载失败时,轮播容器别塌陷
本地测试好好的,一上线就变一条细线——大概率某张图 404 或跨域被拒,<img> 加载失败后高度为 0,整个容器跟着塌。
实操建议:
真正卡住人的从来不是“怎么动起来”,而是“为什么这张图没消失”“为什么定时器越切越快”“为什么一放服务器就空白”——这些问题都藏在 display 切换顺序、定时器清理时机、图片加载容错这三处。











