display: none 切换是最稳的起点,需先确保结构正确(容器、图片、按钮)、js显隐逻辑清空再设、自动轮播配暂停重置,高度不固定时用opacity替代可避免重排。

display: none 切换是最稳的起点,别一上来就搞 transform 或 opacity 动画——先把“只显示一张图”这件事做对,比“动得漂亮”重要十倍。
先搭三块拼图:容器、图片、按钮
轮播不是靠 JS 魔法变出来的,而是结构对了,JS 才能控制。浏览器原生不提供轮播组件,但用三个基础元素就能跑起来:
<div class="carousel"> 作为外层容器,加 <code>overflow: hidden防止图片溢出<div class="carousel-images"> 包住所有 <code><img>,每张图带alt和固定宽高(比如width="600" style="max-width:90%")- 导航按钮用
<button type="button" data-index="0"></button>,不用<a></a>或<span></span>,避免默认跳转或焦点干扰 - 用
document.querySelectorAll('.carousel-images img')拿到全部图片节点 - 在
showImage(index)函数里,先slides.forEach(s => s.style.display = 'none') - 再
slides[index].style.display = 'block',注意索引越界要检查:if (index = slides.length) return - 别用
visibility: hidden替代 —— 它仍占布局空间,可能把容器撑高,导致页面跳动 - 定义全局变量
let carouselTimer = null - 每次启动前先
clearInterval(carouselTimer),再carouselTimer = setInterval(...) - 给
.carousel绑mouseenter(暂停)和mouseleave(恢复),移动端可跳过 - 点击按钮后也调一次
resetTimer(),否则刚切到第2张,0.5秒后又跳第3张 - 最简单解法:给
.carousel加固定高度,如height: 400px - 若必须自适应,改用
opacity: 0 / opacity: 1+pointer-events: none,但得额外加transition: opacity 0.3s - 注意:用
opacity时,隐藏图仍响应事件,所以必须同步关掉pointer-events,否则用户可能误点到背后图片
常见错误:直接写一串 <img src="a.jpg"><img src="b.jpg"> 没容器,JS 找不到上下文;或者用 <picture></picture> 开头就加响应式,调试时根本看不出哪张在显示。
JS 控制显隐必须清空再设
切换逻辑崩,90% 出在顺序错了。不能只给目标图设 display: block,必须先遍历所有 <img> 把 display 清成 none,再设当前索引的为 block:
自动轮播必须配暂停和重置
setInterval(() => next(), 3000) 单独写是危险操作,用户点按钮后定时器还在跑,下一张会立刻切走,体验极差:
别用 setTimeout 递归模拟轮播——容易堆栈溢出,且无法统一清理。
高度不固定时 display 切换会重排
如果轮播容器高度随图片内容变化(比如没设死 height),display: none → block 切换会触发浏览器重排,页面可能抖一下:
真正卡住新手的,从来不是“怎么动”,而是“为什么动完页面跳了”“点按钮没反应”“第二张出来第一张还露半截”——这些问题全在结构和清除逻辑里,不在动画参数上。











