Skip to content
Knsept
Free playbook

Scroll-snap carousel

A swipeable carousel built on native scrolling and CSS scroll snap, with arrow buttons and dots that track the current slide.

CSSJavaScriptUI Widgets Updated Oct 23, 2026
Live demo Reduced motion is on, so effects are toned down
<section class="carousel" aria-roledescription="carousel" aria-label="Featured projects">
  <div class="carousel-track" tabindex="0">
    <article class="slide" aria-roledescription="slide" aria-label="1 of 4" style="--slide-color: #3684ff"><b>Launch</b><span>Ship the first version</span></article>
    <article class="slide" aria-roledescription="slide" aria-label="2 of 4" style="--slide-color: #12a150"><b>Measure</b><span>Watch what people use</span></article>
    <article class="slide" aria-roledescription="slide" aria-label="3 of 4" style="--slide-color: #e08a1e"><b>Learn</b><span>Talk to real users</span></article>
    <article class="slide" aria-roledescription="slide" aria-label="4 of 4" style="--slide-color: #c93a3f"><b>Repeat</b><span>Small steps, every week</span></article>
  </div>
  <div class="carousel-controls">
    <button class="carousel-arrow" type="button" data-direction="-1" aria-label="Previous slide">←</button>
    <div class="carousel-dots"></div>
    <button class="carousel-arrow" type="button" data-direction="1" aria-label="Next slide">→</button>
  </div>
</section>

The carousel is just a horizontal scroller with scroll-snap-type: x mandatory, so swiping on a phone, trackpad scrolling and momentum all behave exactly like the platform expects. No drag code, no transform math.

The script adds dots and arrows on top, and an IntersectionObserver (with the track as its root) marks a slide as current once 60% of it is visible. That keeps the dots in sync no matter how the slide got there: a swipe, an arrow, a dot or the keyboard.

aria-roledescription tells screen readers this is a carousel of slides, and each slide is labelled "2 of 4". With reduced motion on, arrow and dot jumps happen instantly instead of smooth-scrolling.

Use real images: put an <img> inside each .slide with object-fit: cover.

More from the library

Images & media live

Before/after slider

Drag to compare two images. Built on a native range input, so mouse, touch and keyboard all work for free.

Navigation live

Smooth accordion

A FAQ accordion built on native details/summary, with a smooth open and close animation and an optional one-open-at-a-time mode.

Scroll & motion live

Count-up stats

Numbers that count up when they scroll into view, with easing and formatting. A quicker count with reduced motion.