Frontend Development 7 min read

Build a Lightweight Carousel with CSS Scroll‑Snap and Minimal JavaScript

This article demonstrates how to replace heavy swiper libraries with a slim, pure‑CSS carousel using scroll‑snap‑type, scroll‑snap‑align, and scroll‑behavior, and adds a small JavaScript polyfill for smooth scrolling and automatic slide rotation, complete with npm packaging and compatibility notes.

Yuewen Frontend Team
Yuewen Frontend Team
Yuewen Frontend Team
Build a Lightweight Carousel with CSS Scroll‑Snap and Minimal JavaScript

Background

Traditional swiper libraries are bulky because they include many unnecessary features; the author wanted a simple scrolling effect with as little code as possible, exploring whether pure CSS effects could replace the heavy library.

Implementation Idea

scroll-snap-type makes the container automatically align to a specified element when scrolling stops, acting like an “magnet” that pulls the child into view. scroll-snap-align defines the alignment point (start, center, end) for each child element, determining where the snap occurs.

To achieve smooth scrolling, scroll-behavior: smooth adds a built‑in animation that makes the movement feel natural.

Combining these three CSS properties creates a smooth, automatic carousel. JavaScript is then used to advance the slides at intervals.

<code>.swiper-box {
  scroll-behavior: smooth;
  scroll-snap-type: x mandatory;
}
.swiper-image {
  scroll-snap-align: start;
}

setInterval(function () {
  var clientWidth = ele.clientWidth;
  var index = Math.floor(ele.scrollLeft / clientWidth) + 1;
  if (index > imageList.length - 1) {
    index = 0;
  }
  eleSwiperBox.scrollLeft = clientWidth * index + _ele.offsetLeft * index;
}, 3000);
</code>

If a browser does not support scroll-behavior: smooth , a polyfill recursively adjusts scrollLeft in small steps until the target position is reached.

<code>if (!CSS.supports("scroll-behavior: smooth")) {
  var step = function () {
    var distance = scrollLeft - ele.scrollLeft;
    if (Math.abs(distance) <= 3) {
      ele.scrollLeft = scrollLeft;
    } else {
      ele.scrollLeft += distance / 4;
      requestAnimationFrame(step);
    }
  };
  step();
} else {
  ele.scrollLeft = scrollLeft;
}
</code>

After adding the polyfill, the carousel works across browsers, including Safari, which lacks native support for the CSS properties.

Not Only for Carousel

The same CSS properties can be used for click‑triggered smooth scrolling, providing a lightweight solution for various scrolling interactions.

Component Packaging

The code is wrapped into an npm package snap‑swiper , allowing easy installation and reuse in projects without framework constraints. It also includes lazy‑loading and error handling for images.

<code>npm i snap-swiper

import "snap-swiper/snap-swiper.css";
const snapSwiper = require("snap-swiper");
snapSwiper({
  imageList: [],
  el,
});
</code>

References

[1] scroll‑snap‑type: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-type

[2] scroll‑snap‑align: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-align

[3] scroll‑behavior: https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior

[4] CSS guidance: https://www.zhangxinxu.com/

[5] Code repository: https://github.com/yued-fe/snap-swiper

[6] Demo sandbox: https://codesandbox.io/s/gifted-ives-zco4l?file=/index.html

[7] GitHub source: https://github.com/yued-fe/snap-swiper

[8] CSS scroll‑snap event detection: https://www.zhangxinxu.com/wordpress/2019/04/css-scroll-snap-event-element-detect/

[9] Introduction to CSS scroll‑snap: https://www.zhangxinxu.com/wordpress/2018/11/know-css-scroll-snap/

FrontendjavascriptCSSpolyfillCarouselscroll-snap
Yuewen Frontend Team
Written by

Yuewen Frontend Team

Click follow to learn the latest frontend insights in the cultural content industry. We welcome you to join us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.