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?
DEV3 Developer Forum
How do I build a swipeable carousel with CSS scroll-snap and no JavaScript?
Every post is reviewed first. Usually reviewed within 24 hours.
1 reply
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.