Swiper alternatives for React, by what you’re actually escaping
Nobody leaves Swiper because it is bad — it is the most complete slider there is. People leave over weight (≈40 kB before modules), over inheriting its DOM and CSS, or because their "slider" was never really slides. Each complaint has a different best answer.
| Swiper | Embla | keen-slider | react-horizontal-scrolling-menu | |
|---|---|---|---|---|
| Bundle (core, min+gzip) | ≈40 kB | ≈8 kB | ≈7 kB | ≈5.7 kB |
| Model | Slides, batteries included | Slides, headless | Slides, minimal engine | Items in a native scroll row |
| Effects & modules | Richest available | Plugins / DIY | Some built in | None — recipes instead |
| Owns the gesture layer | Yes (transforms) | Yes (transforms) | Yes (transforms) | No — browser scrolls |
| Per-item visibility | Slide-index events | Slide-index events | Slide-index events | Built in (useIsVisible) |
| Best swap when | — | You style everything anyway | Minimal slider, no React lock-in | The "slides" are clickable items |
Sizes are approximate cores — Swiper’s grows with imported modules, which also means a trimmed Swiper build is smaller than its reputation.
Escaping the kilobytes: Embla or keen-slider
If the product is a real carousel — snapping, one page of slides at a time — the lightweight engines are drop-in-close:
- Embla (≈8 kB): headless, superb physics, first-class React hook, the engine under shadcn/ui's carousel. You bring all markup and CSS — which is the point.
- keen-slider (≈7 kB): a minimal framework-agnostic engine, good when the same slider must ship to React and non-React surfaces.
Both keep the transform-based slide model, so effects like fade or coverflow stay DIY — if you rely on those, a trimmed Swiper build is honestly the better answer than re-implementing them.
Escaping the slide model: the menu-shaped case
The other exit is for builds where Swiper's slide semantics were never load-bearing: category rows, logo walls, tab strips, chip bars, product rails. The tells are configuration like slidesPerView: 'auto' plus freeMode: true — that pair is Swiper being asked to impersonate native scrolling.
react-horizontal-scrolling-menu (≈5.7 kB) is that native scrolling, plus the parts the browser doesn't ship: per-item visibility, scroll-to-item, edge-aware arrows and drag that doesn't break clicks. No effects, no snapping, no gesture emulation — see the Netflix-row, tabs and chip-bar pages, or the full table.
A fair warning in both directions
Migrating off Swiper to save weight and then hand-building autoplay, pagination, a11y announcements and effects is how a 40 kB problem becomes a person-month problem. Swap to a lighter engine when your usage is genuinely a subset — and to a scrolling menu only when the slide semantics were fake all along. If you use Swiper’s depth, keep Swiper.