611a13f0884f248fc7d4cb84b837b0af8bd9987d
@ilia/carousel
Tiny, framework-agnostic scroll-snap carousel. Zero runtime deps. Native scroll handles touch/momentum, CSS handles snap + motion, JS is a thin layer.
- core ≤1 KB gzip · dots ≤0.6 KB · autoplay ≤0.6 KB
- Ships unminified ESM — your bundler minifies.
Install
This package lives on a private Gitea registry. Point the @ilia scope at it:
# .npmrc
@ilia:registry=https://git.allmy.work/api/packages/ilia/npm/
yarn add @ilia/carousel
Entry points
| Import | What |
|---|---|
@ilia/carousel |
createCarousel(track) core |
@ilia/carousel/dots |
dots() — Firefox/legacy dot fallback (self-gates) |
@ilia/carousel/autoplay |
autoplay() — reduce-motion-aware auto-advance |
@ilia/carousel/carousel.css |
snap track, native markers, opt-in .fx effect |
Usage
<div class="track" id="carousel">
<div class="slide">…</div>
<div class="slide">…</div>
<div class="slide">…</div>
</div>
<button id="prev" aria-label="Previous">‹</button>
<button id="next" aria-label="Next">›</button>
<!-- Firefox/legacy dot fallback; native ::scroll-marker owns dots elsewhere -->
<div id="dots" aria-label="Choose slide">
<button aria-label="Slide 1"></button>
<button aria-label="Slide 2"></button>
<button aria-label="Slide 3"></button>
</div>
import { createCarousel } from '@ilia/carousel';
import { dots } from '@ilia/carousel/dots';
import { autoplay } from '@ilia/carousel/autoplay';
import '@ilia/carousel/carousel.css';
const track = document.getElementById('carousel');
const c = createCarousel(track);
// Arrows are just your own handlers — no module needed.
document.getElementById('next').onclick = () => c.next();
document.getElementById('prev').onclick = () => c.prev();
// Dots: no-ops where native ::scroll-marker exists (no double dots).
dots(c, document.getElementById('dots'));
// Opt-in auto-advance. Provide a visible pause control (see a11y note).
const stop = autoplay(c, { interval: 4000, root: track });
Add the opt-in scroll-driven effect with class="track fx" — it degrades to plain
snap where animation-timeline: view() is unsupported.
Accessibility
autoplay()never starts underprefers-reduced-motion: reduce, and the.fxeffect + smooth scrolling are gated behind@media (prefers-reduced-motion: no-preference).- If you use
autoplay(), you must provide a visible pause/stop control (WCAG 2.2.2) — wire it to the returnedstop(). - Give dot buttons accessible labels (
aria-label).
Browser support
| Feature | Chrome | Safari | Firefox |
|---|---|---|---|
scroll-snap + core path |
✅ | ✅ | ✅ |
::scroll-marker native dots |
✅ 135+ | ✅ 18.2+ | ⚠️ → JS dots() fallback |
scroll-driven .fx |
✅ | ⚠️ partial → plain snap | ✅ |
Index tracking uses IntersectionObserver (universal today); a scrollsnapchange
upgrade is deferred until Firefox ships it.
Release
npm version <patch|minor|major>
git push --follow-tags # CI verifies, runs e2e, publishes on the v* tag