DEV3 Technologies home

DEV3 Developer Forum

How do I build a swipeable carousel with CSS scroll-snap and no JavaScript?

dev3 ·

I need a horizontal product slider that snaps to each card on touch and trackpad. Most libraries add 30 KB of JavaScript. Is there a pure CSS approach and how do I add arrow buttons?

#css#scroll-snap#carousel

0

1 reply

dev3 · Accepted answer

Scroll snap does the heavy lifting

<div class="slider" tabindex="0" role="region" aria-label="Featured products">
  <article class="slide">...</article>
  <article class="slide">...</article>
  <article class="slide">...</article>
</div>
.slider {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 1rem;
  overscroll-behavior-x: contain;
  scrollbar-width: none;           /* hide scrollbar in Firefox */
}
.slider::-webkit-scrollbar { display: none; }

.slide {
  flex: 0 0 min(85%, 320px);
  scroll-snap-align: start;
}

Tailwind equivalent: container flex snap-x snap-mandatory gap-4 overflow-x-auto, slide shrink-0 basis-4/5 snap-start.

Mandatory vs proximity

mandatory always lands on a snap point; proximity only snaps when close, which feels gentler on long content. Prefer proximity if slides can be taller than the viewport.

Arrow buttons need a tiny script

const slider = document.querySelector('.slider');
document.querySelector('#next').onclick = () =>
  slider.scrollBy({ left: slider.clientWidth * 0.8, behavior: 'smooth' });
document.querySelector('#prev').onclick = () =>
  slider.scrollBy({ left: -slider.clientWidth * 0.8, behavior: 'smooth' });

scroll-behavior: smooth in CSS also covers anchor links to slides.

Progressive enhancement

Newer Chrome versions support ::scroll-button() and ::scroll-marker pseudo-elements for CSS-only arrows and pagination dots. Treat them as an enhancement because support is not universal yet.

Accessibility

  • Make the scroller focusable (tabindex="0") so keyboard users can scroll with arrow keys, and give it a label.
  • Respect reduced motion: @media (prefers-reduced-motion: reduce) { .slider { scroll-behavior: auto; } }.
  • Do not hide important content only in later slides.

Pitfall

Padding at the start and end can break snapping; use scroll-padding and scroll-margin instead of margins on the container.

0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.