egjs-flicking: a TypeScript carousel with circular, free-scroll and virtual-scroll modes
🎠♻️ Everyday 30 million people experience. It's reliable, flexible and extendable carousel.
At a glance
- What is it?
- @egjs/flicking is a carousel library from Naver's egjs group, installed from npm as @egjs/flicking, with framework wrappers for React and Vue and a separate plugins package. Its virtual scroll and circular modes are the parts worth evaluating before you commit.
- Who is it for?
- Adopt it if you need one carousel implementation across plain TypeScript, React and Vue, and if circular looping or virtual scroll over a long panel list is a requirement rather than a nice-to-have. Do not adopt it if you only need a single static row of images on one framework, or if you want a component that renders panels for you; Flicking expects you to own the markup and the panel count.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 15 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The carousel problem egjs-flicking is aimed at
A carousel looks trivial until it has to loop, hold momentum, and stay in sync with a framework's render cycle. Most teams end up writing the same three pieces by hand: a transform applied to a container on every pointer move, a snap calculation on release, and a re-measure step when the viewport or the panel list changes. Flicking packages those pieces as a library and exposes them as options rather than as code you maintain.
The intended audience is front-end engineers building the panel-strip pattern on several surfaces at once. The repository is a monorepo, and the packages table lists the core library alongside separate framework packages. That layout tells you the project expects to be consumed through a wrapper when you are in React or Vue, and directly when you are not. The README markets the component as reliable, flexible and extendable, which is the kind of claim every carousel makes; the options list is the part you can actually check.
How Flicking moves panels: camera, viewport and the options that matter
Flicking does not create your slides. The README's HTML example shows the required structure: an outer element carrying the class flicking-viewport, an inner element carrying flicking-camera, and one or more children carrying the class panel. The camera is the element that gets translated; the viewport is the frame it moves inside. If you drop that structure into a component and forget the stylesheet, you get three stacked divs and no carousel, because the classes are what the CSS targets.
On top of that base, the README lists the behaviors the library ships. Circular mode turns the strip into an infinite loop. Free scroll switches from snap-to-panel movement to momentum-based movement that follows the pointer or finger. Virtual scroll renders only the panels that are visible, which is the option to look at when the dataset is large enough that keeping every panel in the DOM is the bottleneck. The plugin package adds AutoPlay, Fade, Parallax, Arrow and Pagination as separate imports rather than as core options, so a build that needs none of them does not carry them.
The library is written in TypeScript and the README states the API is fully typed. For a component whose behavior depends on a long option object, that matters more than it sounds: option names and their accepted values are checked at compile time rather than discovered by reading the source.
Installing @egjs/flicking and getting a first carousel on screen
Install the core package from npm. The README gives this exact command, with the leading dollar sign as a prompt marker rather than part of the command:
npm install --save @egjs/flickingIf you would rather not go through a bundler, the README also lists CDN builds on jsDelivr, unpkg and cdnjs, and shows a packaged script at dist/flicking.pkgd.min.js that includes the dependencies.
The markup has to come first. This is the structure the README requires, and it is the same whether you initialize from a module or from a script tag:
<div id="my-flicking" class="flicking-viewport">
<div class="flicking-camera">
<div class="panel"></div>
<div class="panel"></div>
<div class="panel"></div>
</div>
</div>Then import the class and the stylesheet, and construct it against a selector. The README's ES module example is two imports and one constructor call:
import Flicking from "@egjs/flicking";
import "@egjs/flicking/dist/flicking.css";
const flicking = new Flicking("#my-flicking", { circular: true });What you should see is a horizontal strip of the three panels that snaps between positions, and with circular set to true it wraps instead of stopping at the ends. The README notes that the HTML structure is not something you need to think about when using Flicking with the frameworks, since the wrapper packages handle it. If you are starting in React or Vue, install the matching package from the monorepo instead of wiring the core library by hand.
Where Flicking is the wrong tool
The markup requirement is the first real constraint, and it is not cosmetic. Flicking assumes it owns the element it is initialized on and the nesting inside it. If your panels come from a design system component that renders its own wrapper, or from a third-party grid that inserts intermediate elements, you are now fighting the viewport and camera structure rather than using it. The README does not document an escape hatch for that case.
The second constraint is scope. Flicking is a carousel, and the plugins package covers the carousel-adjacent features: autoplay, fade, parallax, arrows, pagination. It is not a general layout engine and it is not a virtualized list. If your actual problem is rendering ten thousand rows in a scrollable container, virtual scroll inside a carousel solves a different problem, and the related searches that point at egjs/infinitegrid are pointing at a separate project for a reason. Reaching for Flicking because it happens to have a virtual scroll option is a reasonable way to end up with a carousel you did not want.
The third is maintenance expectation. The last push to the repository was on 2026-09-16, and the most recent release listed is 4.17.0 on 2026-09-08. That is a live project, but it also means the version you pin today is one of several releases in a short window, and the upgrade path between minor versions is something you should read the changelog for rather than assume.
Flicking against Swiper and the plain CSS scroll-snap approach
The closest widely used alternative is Swiper, and the difference is mostly in who owns the DOM. Swiper's default mode builds the slide wrapper and the slide elements for you from your content, which is convenient when you have a list of items and no strong opinion about the markup. Flicking inverts that: you supply flicking-viewport, flicking-camera and panel yourself, and the library only translates the camera. That inversion is why the framework wrappers exist. In React or Vue you want the wrapper to produce the structure so your component tree stays declarative.
The other alternative is not a library at all. CSS scroll-snap gives you snapping between elements with no JavaScript, and for a static strip of images on a modern browser it is often enough. What it does not give you is circular looping, programmatic control over the current panel, or virtualization. The moment you need any of those three, you are back to a library, and the choice becomes which one.
If you are already inside the egjs ecosystem, the related components linked from the README are the natural comparison set rather than Swiper, since they share the same release cadence and the same organization behind them.
Licence, monorepo cost and what an upgrade actually involves
The repository is MIT licensed, and the README carries a licence badge pointing at the LICENSE file at the repository root. MIT is permissive and imposes no obligation to publish your own source. There is also a NOTICE file at the top level, which is common in projects that carry third-party attributions; if your organization runs a licence scan, that file is the one to read alongside LICENSE. None of this is legal advice, and the terms that bind you are the ones in the files themselves.
The cost of adopting Flicking is mostly the cost of the monorepo's shape. The root package.json is private and named @egjs/root, and the workspace is driven by pnpm, with scripts such as dev:flicking, dev:react, dev:vue and dev:plugins for local development and a test script that runs the unit suite. That matters if you intend to patch the library or contribute: you are working in a pnpm workspace, not in a single package you can clone and build in isolation. If you are only consuming it from npm, the workspace layout is invisible to you, and the upgrade cost is the ordinary one of reading the changelog between the version you pinned and the version you move to.
One detail worth noting for anyone who vendors the source: the root package.json declares sideEffects for CSS and Sass files. That is the signal a bundler needs to avoid tree-shaking the stylesheet away, and it is the kind of thing that silently breaks a carousel when a build configuration is changed.
Editorial conclusion
Adopt it if you need one carousel implementation across plain TypeScript, React and Vue, and if circular looping or virtual scroll over a long panel list is a requirement rather than a nice-to-have. Do not adopt it if you only need a single static row of images on one framework, or if you want a component that renders panels for you; Flicking expects you to own the markup and the panel count. Before writing any application code, verify three things in your own environment: that the CSS from @egjs/flicking/dist/flicking.css is actually loaded, since the viewport and camera classes are what the layout depends on, that your chosen option set behaves as you expect on a touch device, and that the panel count you feed into virtual scroll matches what the data source can produce at the edges of the list.
Frequently asked questions
How do I install egjs-flicking?
Install the core package with npm install --save @egjs/flicking. The README also lists CDN builds on jsDelivr, unpkg and cdnjs if you prefer not to use a bundler.
What HTML structure does egjs-flicking require?
Flicking needs an outer element with the class flicking-viewport, an inner element with the class flicking-camera, and one or more children with the class panel. The README notes you do not need to think about this when using Flicking with the framework wrappers.
Does egjs-flicking support React and Vue?
Yes. The repository is a monorepo containing the core library plus separate React and Vue packages, and the root package.json has dev scripts for flicking, react and vue. The README says the framework packages handle the required HTML structure for you.
What plugins does egjs-flicking provide?
The README lists AutoPlay, Fade, Parallax, Arrow and Pagination as plugins available through @egjs/flicking-plugins. They are a separate package rather than options on the core library.
Is egjs-flicking free to use in commercial projects?
The repository is MIT licensed, which is permissive and does not require you to publish your own source. The LICENSE file at the repository root is the document that governs use, and a NOTICE file is also present at the top level.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/naver-egjs-flicking)