๐ŸŽ  Projects

Build an Image Slider from Scratch โ€” Autoplay, Dots, Swipe

๐Ÿ“… Jul 5, 2026 โฑ 4 min read

The CSS scroll-snap version covers most needs โ€” build THIS version to understand what libraries do: state + transform.

The engine

<div class="slider">
  <div class="track">
    <img src="1.jpg"><img src="2.jpg"><img src="3.jpg">
  </div>
  <button class="prev">โ€น</button><button class="next">โ€บ</button>
  <div class="dots"></div>
</div>
.slider { overflow: hidden; position: relative; }
.track  { display: flex; transition: transform .4s ease; }
.track img { flex: 0 0 100%; }
let index = 0;
const count = track.children.length;

function go(i) {
  index = (i + count) % count;                     // wraps both directions
  track.style.transform = `translateX(-${index * 100}%)`;
  dots.forEach((d, j) => d.classList.toggle("active", j === index));
}

nextBtn.onclick = () => go(index + 1);
prevBtn.onclick = () => go(index - 1);

// autoplay + pause on hover
let auto = setInterval(() => go(index + 1), 4000);
slider.onmouseenter = () => clearInterval(auto);
slider.onmouseleave = () => auto = setInterval(() => go(index + 1), 4000);

Touch swipe (the mobile 20%)

let startX = 0;
track.addEventListener("touchstart", (e) => startX = e.touches[0].clientX);
track.addEventListener("touchend", (e) => {
  const dx = e.changedTouches[0].clientX - startX;
  if (Math.abs(dx) > 50) go(index + (dx < 0 ? 1 : -1));
});

Accessibility: aria-label on buttons, pause autoplay when prefers-reduced-motion.

โ† All Articles