drag-scroll-carousel
v1.0.8
Published
Lightweight drag-scroll for horizontal containers with optional buttons. One class, zero dependencies, framework-agnostic.
Maintainers
Readme
drag-scroll-carousel
Add drag-scroll to any horizontal container with one class.
A tiny, zero-dependency behavior layer for smooth mouse and touch drag scrolling. It is not a UI kit: it does not dictate layout, spacing, or markup—only scroll behavior.
Features
- Auto-init — Elements with class
drag-carouselare ready onDOMContentLoaded; no duplicate setup per element - Mouse + touch — Desktop drag and mobile touch drag using native
scrollLeft - Configurable speed — Default multiplier
1.5 - Optional prev/next — Wire buttons with CSS selectors; each click scrolls by one viewport width with smooth behavior
- Center mode (optional) — Buttons/drag can snap to the nearest slide center
- Loop mode (optional) — Seamless looping using cloned slides; works even with small sets (for example
< 3slides) - Minimal inline styles —
overflow-x: auto,cursor: grab,scroll-behavior: smooth(plus optionalstyle.cssforgrabbing)
Install
npm install drag-scroll-carouselconst DragCarousel = require("drag-scroll-carousel");Quick start (browser)
- Add a horizontal row of children (your own layout: flex, grid, etc.).
- Put the library on the page, then add class
drag-carouselto the scroll container.
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/drag-scroll-carousel@1/style.css"
/>
<div class="drag-carousel">
<div>Slide A</div>
<div>Slide B</div>
<div>Slide C</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/drag-scroll-carousel@1/index.js"></script>After load, window.DragCarousel is available. Auto-init runs on DOMContentLoaded for every .drag-carousel.
Manual init (e.g. custom speed or arrows):
<div id="strip"></div>
<button type="button" id="prev" aria-label="Previous">←</button>
<button type="button" id="next" aria-label="Next">→</button>
<script src="https://cdn.jsdelivr.net/npm/drag-scroll-carousel@1/index.js"></script>
<script>
new DragCarousel("#strip", {
speed: 1.5,
centerMode: true,
loop: true,
buttons: { prev: "#prev", next: "#next" },
});
</script>Do not put class="drag-carousel" on the same node if you also call new DragCarousel on it with options (avoid double init).
CDN URLs
Use a major tag (@1) or pin an exact version (@1.0.0) in production.
| Asset | jsDelivr | unpkg | | ----- | -------- | ----- | | Script | cdn.jsdelivr.net/npm/drag-scroll-carousel@1/index.js | unpkg.com/drag-scroll-carousel@1/index.js | | Styles (optional) | cdn.jsdelivr.net/npm/drag-scroll-carousel@1/style.css | unpkg.com/drag-scroll-carousel@1/style.css |
Live example (bundled demo)
The package includes HTML examples under examples/:
| Demo | What it is |
| ---- | ----------- |
| examples/demo-cdn.html | Full page on unpkg — loads the library from the CDN, fetches sample products from api.escuelajs.co, drag + prev/next. Requires the version to exist on npm. |
| examples/demo-react-cdn.html | React 18 via CDN + Babel; fetches products from api.escuelajs.co, then uses useEffect + useRef + destroy() with DragCarousel. |
| examples/demo.html | Same UI with relative script paths — run a static server from the repo root (see below). |
Run the local demo (clone or npm install drag-scroll-carousel, then serve the package root over http://, not file://):
npm run demoOpen http://localhost:5173/examples/demo.html — or http://localhost:5173/demo.html, which redirects to the example folder.
Shopify (Liquid)
Load the script and optional CSS in your theme (e.g. theme.liquid or section assets).
<div class="drag-carousel">
{% for product in collections.frontpage.products %}
<div>{{ product.title }}</div>
{% endfor %}
</div>Style the row/cards yourself (flex, grid, etc.). After dynamic HTML (e.g. section AJAX), call:
DragCarousel.initAll();React usage
Use a ref and initialize in useEffect on the client. Call destroy() in cleanup.
import { useEffect, useRef } from "react";
import DragCarousel from "drag-scroll-carousel";
import "drag-scroll-carousel/style.css"; // optional
export default function ProductRow() {
const stripRef = useRef(null);
useEffect(() => {
if (!stripRef.current) return;
const carousel = new DragCarousel(stripRef.current, { speed: 1.5 });
return () => carousel.destroy();
}, []);
return (
<div ref={stripRef} className="my-horizontal-row">
{/* your cards */}
</div>
);
}For Next.js App Router, put this in a client component ("use client").
API
new DragCarousel(selectorOrElement, options?)
| Option | Type | Default | Description |
| ------ | ---- | ------- | ----------- |
| speed | number | 1.5 | Multiplier for pointer movement vs. scroll |
| buttons | object | null | { prev: string, next: string } — any valid querySelector string |
| centerMode | boolean | false | Snaps to the nearest slide and centers it after drag/end; buttons move by slide |
| loop | boolean | false | Enables infinite looping by cloning slides before/after the original set |
| slideSelector | string \| null | null | Selector used to identify slides; defaults to direct children of the container |
| minLoopSlides | number | 3 | Minimum visual slide count for loop cloning (helps when your source has very few slides) |
Selectors resolve with document.querySelector (first match).
DragCarousel.initAll()
Initializes every .drag-carousel in the document that is not already initialized. Use after injecting new markup.
DragCarousel.isInitialized(element)
Returns whether the element already has carousel behavior.
instance.destroy()
Removes all listeners from the carousel instance and allows re-initializing the same element later.
Constraints
- No React required; no bundler required for browser usage
- Intended for direct use via
<script>or small bundles
License
MIT
