Swiper still rules the feature list, but its core + styles weigh in around 80 KB min (≈ 25 KB gzip). If you’d rather spend those bytes on i18n, analytics or CSS vars, try one of these leaner carousels — all MIT‑licensed except where noted, all boasting 1 k+ GitHub stars.

One’s bloated. One’s built to move.

* Size excludes the optional Slick theme CSS. † Flickity is free for OSS, but requires a commercial license for paid projects.
1. Keen Slider — pixel‑perfect “app” swipes
- DX: Replace
<SwiperSlide>with a plain<div>and import theuseKeenSliderhook. That’s it.
Quick start
import { useKeenSlider } from "keen-slider/react";export default function Gallery() { const [sliderRef] = useKeenSlider( { loop: true, mode: "free-snap", slideChanged: s => console.log(s.details()) } ); return ( <div ref={sliderRef} className="keen-slider h-64"> {[1,2,3,4].map(n => ( <div key={n} className="keen-slider__slide flex items-center justify-center text-4xl"> {n} </div> ))} </div> );}
Extra patterns you’ll love

Table with patterns
- Fun fact: Originally crafted for industrial touch‑terminals so grape pickers could browse data in gloves — hence its obsession with gesture accuracy.
2. Embla Carousel — build‑it‑your‑way
- DX: You get a tiny core; every extra (looping, autoplay, wheel gestures) is an opt‑in plugin.
Minimal React shell
import useEmblaCarousel from "embla-carousel-react";import Autoplay from "embla-carousel-autoplay";const options = { align: "start", loop: true };const plugins = [Autoplay({ delay: 3000 })];function Headlines({ articles }) { const [viewportRef] = useEmblaCarousel(options, plugins); return ( <section className="overflow-hidden" ref={viewportRef}> <div className="flex"> {articles.map(a => ( <a key={a.id} className="flex-none w-full md:w-1/2 lg:w-1/3 pr-6" href={a.url}> <img src={a.img} className="rounded-xl" /> <h3>{a.title}</h3> </a> ))} </div> </section> );}
Why pick Embla?
- Plugin model — only pay for what you import: wheel gestures, drag‑free, 3D tilt, autoplay, parallax, etc.
- Headless — layout entirely yours (CSS Grid, Tailwind, anything).
- Docs you can edit — every code snippet sits in a live CodeSandbox PR.
Pro tip: Combine embla-carousel-solid or embla-carousel-svelte in micro‑frontends — you’ll share physics while mixing frameworks.
3. Glide.js — the happy medium
- DX: Few options (
gap,peek,perView) deliver 90 % of use‑cases. Works in ES modules, no build step needed.
ESM‑only install
npm i @glidejs/glide
import Glide from "@glidejs/glide";const glide = new Glide(".glide", { perView: 3, gap: 24, peek: { before: 50, after: 50 }, animationDuration: 600,}).mount();
Recipes

Scenario examples
Fun fact: Glide’s creator open‑sourced it after using the very first version on a Polish newspaper site back in 2013 — it’s been in production ever since.
4. React Slick — least friction for newcomers
- DX: Just
<Slider settings={…}>; no custom CSS required. Huge snippet library on CodeSandbox.
Classic example with custom arrows
import Slider from "react-slick";import "slick-carousel/slick/slick.css";const NextArrow = props => <button {...props} className="right-2">›</button>;const PrevArrow = props => <button {...props} className="left-2">‹</button>;export default function LogoStrip({ logos }) { const settings = { arrows: true, slidesToShow: 5, infinite: true, nextArrow: <NextArrow />, prevArrow: <PrevArrow />, responsive: [ { breakpoint: 1024, settings: { slidesToShow: 3 } }, { breakpoint: 640, settings: { slidesToShow: 2, arrows: false } }, ], }; return <Slider {...settings}>{logos.map(l => <img key={l} src={l} />)}</Slider>;}
When Slick shines
- Training junior devs — API mirrors jQuery Slick docs from 2015, tons of snippets.
- SSR & Next.js — proven workarounds (
import dynamic) and examples for hydration issues. - Legacy hand‑off — jQuery/Slick and React Slick share the same option names, easing rewrites page‑by‑page.
Fun fact: Under the hood it’s a React port of the jQuery “Slick” slider, so blog posts from 2015 still help.
5. Flickity — delightfully “springy”
- DX: Vanilla JS + a thin
react-flickity-componentwrapper. Known for polished “rubber‑band” drag inertia.
React wrapper
import Flickity from "react-flickity-component";import "flickity/css/flickity.css";const flickityOptions = { cellAlign: "left", contain: true, wrapAround: true, groupCells: 2, pageDots: false,};export function Portfolio({ shots }) { return ( <Flickity options={flickityOptions} className="overflow-visible"> {shots.map(s => ( <figure key={s.id} className="mr-4 w-80"> <img src={s.img} className="rounded-2xl" /> <figcaption className="mt-2">{s.caption}</figcaption> </figure> ))} </Flickity> );}
Why users stay
- Rubber‑band feel — subtle “spring” easing distinguishes it from any CSS‑only slider.
- GroupCells — grid‑like carousels for product cards with two lines of config.
- Masonry compatibility — share the optional
masonryadd‑on for Pinterest‑style layouts.
Heads‑up: Commercial license is $99 one‑off — still cheaper than shipping Mb‑heavy bundles every month.
- Fun fact: Its author added the elastic effect after a late‑night pinball session; users kept it as a signature.
Choosing quickly
- Need 1‑hour migration from Swiper? Keen Slider.
- Want granular control & plugins? Embla.
- Prefer long‑term stability? Glide.js.
- Teaching juniors / doing SSR? React Slick.
- Obsessed with tactile feel? Flickity.
Any of these will shave ~40‑50 KB off a Swiper‑based bundle without costing users a single gesture.
Thank you for being a part of the community
*Before you go:*️️
- Follow us: X | LinkedIn | YouTube | Newsletter | Podcast | Differ | Twitch
- Check out CoFeed, the smart way to stay up-to-date with the latest in tech 🧪
- Start your own free AI-powered blog on Differ 🚀
- Join our content creators community on Discord 🧑🏻💻
- For more content, visit plainenglish.io + stackademic.com