新手手写轮播图核心是三件事:结构用.carousel包.carousel-images及独立并设宽高;样式禁用left/margin、用display切换显隐;JS需clearInterval+isPaused开关控制定时器,防重叠与内存泄漏。

轮播图不是必须用框架才能做,新手从零手写一个能跑、不崩、可调试的版本,核心就三件事:结构别乱套、样式别触发重排、JS 别让定时器失控。
HTML 结构必须用 .carousel 包住独立 <img> 标签
常见错误是直接写一堆 <img src="a.jpg"><img src="b.jpg"> 塞进 <div> 里——没有统一容器和语义类名,后续 JS 找不到元素,CSS 也没法批量控制。更糟的是用 <code><ul><li><img></li></ul>,<li> 默认带 margin 和 list-style,会引入不可控间隙。
正确写法只用两层 <div>:
<pre class="brush:php;toolbar:false;"><div class="carousel">
<div class="carousel-images">
@@##@@
@@##@@
@@##@@
</div>
</div></pre>
<ul>
<li>
<code>width 和 height 必须写死,否则图片加载中容器高度塌陷,导致页面跳动
<img src="1.jpg" alt="slide 1" style="max-width:90%" style="max-width:90%"> 默认不显示,靠 JS 控制 style.display,别用 <picture></picture> 或懒加载属性干扰初始渲染<img src="2.jpg" alt="slide 2" style="max-width:90%" style="max-width:90%"> 加 position: absolute —— 容易脱离文档流,父容器无法自动撑高CSS 只设 overflow: hidden + 固定容器宽高,禁用 left/margin 动画
新手最容易卡在“图片不动”或“一动就卡顿”,问题常出在 CSS 动画方式上。用 left 或 margin-left 移动会强制浏览器重排(reflow),尤其在低端设备上明显掉帧;而 opacity 切换虽平滑,但透明图仍占位、响应点击,容易误触。
最稳妥的隐藏/显示方案是纯 display 切换:
.carousel {
width: 600px;
height: 400px;
overflow: hidden;
position: relative;
}
.carousel-images img {
display: none;
width: 600px;
height: 400px;
}
.carousel-images img.active {
display: block;
}
- 容器
height必须固定,否则display: none → block会触发重排,页面“抖一下” - 别用
visibility: hidden替代display: none—— 它仍占布局空间,可能把下方内容顶下去 - 如果想加淡入效果,只对
.active加transition: opacity 0.3s,其他状态保持display: none
setInterval 必须配 clearInterval + 暂停开关,手动切换后不重置计时器就是 bug
只写 setInterval(nextSlide, 3000) 是典型新手陷阱:用户刚点到第2张,0.5秒后又切到第3张;鼠标悬停时还在切;刷新页面后多个定时器并发运行,CPU 占用飙升。
正确逻辑用一个布尔开关 + 显式启停:
let timer = null;
let isPaused = false;
const startTimer = () => {
if (timer) clearInterval(timer);
timer = setInterval(() => {
if (!isPaused) nextSlide();
}, 3000);
};
// 鼠标悬停暂停
document.querySelector('.carousel').addEventListener('mouseenter', () => {
isPaused = true;
});
document.querySelector('.carousel').addEventListener('mouseleave', () => {
isPaused = false;
startTimer(); // 移开后立刻恢复,不是等3秒
});
// 点击按钮也暂停并重置
document.querySelectorAll('.carousel-nav-btn').forEach(btn => {
btn.addEventListener('click', () => {
isPaused = true;
startTimer(); // 重置倒计时
});
});
- 每次调用
startTimer()前必须先clearInterval(timer),否则旧定时器还在跑 - 移动端没有
mouseenter,如需支持触摸暂停,得补touchstart事件 - 页面卸载前(如用户关闭标签页)应调用
clearInterval(timer),防止内存泄漏
真正难的不是让图片动起来,而是让动的过程不干扰用户操作、不破坏页面布局、不留下残留定时器——这些细节没处理好,轮播图就会在真实项目里反复出问题。












