https://github.com/richardscarrott/react-snap-carousel
DOM-first, headless carousel for React
https://github.com/richardscarrott/react-snap-carousel
carousel react scrolling slideshow typescript
Last synced: 19 days ago
JSON representation
DOM-first, headless carousel for React
- Host: GitHub
- URL: https://github.com/richardscarrott/react-snap-carousel
- Owner: richardscarrott
- License: mit
- Created: 2022-12-19T19:18:08.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-12-19T11:35:02.000Z (6 months ago)
- Last Synced: 2025-04-13T23:54:09.957Z (about 2 months ago)
- Topics: carousel, react, scrolling, slideshow, typescript
- Language: TypeScript
- Homepage: https://richardscarrott.github.io/react-snap-carousel/
- Size: 6.73 MB
- Stars: 324
- Watchers: 3
- Forks: 15
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# React Snap Carousel ðŦ°
[](https://www.npmjs.com/package/react-snap-carousel)
[](https://www.npmjs.com/package/react-snap-carousel)
[](https://github.com/richardscarrott/react-snap-carousel/actions/workflows/node.js.yml)
[](https://github.com/richardscarrott/react-snap-carousel/blob/main/LICENSE)DOM-first, headless carousel for React.
React Snap Carousel leaves the DOM in charge of scrolling and simply computes derived state from the layout, allowing you to progressively enhance a scroll element with responsive carousel controls.

ð§ Utilizes native browser scrolling & CSS scroll snap points for best performance and UX
ð Computes responsive page state from DOM layout & scroll position
ðē Dynamic page-based CSS snap point rendering
ð Headless design, giving you full control over UI using React Hooks API
ðïļ Written in TypeScript
ðŠķ [Lightweight (~1kB)](https://bundlephobia.com/package/react-snap-carousel) + zero dependencies
## Install
```
npm install react-snap-carousel
```## Resources
ðĨ[StoryBook Examples](https://richardscarrott.github.io/react-snap-carousel/)ðĨ
[CodeSandbox StarterKit](https://codesandbox.io/s/react-snap-carousel-49vu6p?file=/src/Carousel.tsx)
[Beginners Tutorial](https://dev.to/richardscarrott/build-your-own-carousel-component-with-react-snap-carousel-1e11)
## Usage
React Snap Carousel doesn't expose a ready-made `` component and instead offers a single export `useSnapCarousel` which provides the state & functions necessary to build your own carousel component.
The following code snippet is a good starting point.
> Inline styles are used for simplicity. You can use whichever CSS framework you prefer.
> You can see it in action on [CodeSandbox](https://codesandbox.io/s/react-snap-carousel-49vu6p?file=/src/Carousel.tsx).
```tsx
// Carousel.tsx
import React, { CSSProperties } from 'react';
import { useSnapCarousel } from 'react-snap-carousel';const styles = {
root: {},
scroll: {
position: 'relative',
display: 'flex',
overflow: 'auto',
scrollSnapType: 'x mandatory'
},
item: {
width: '250px',
height: '250px',
flexShrink: 0
},
itemSnapPoint: {
scrollSnapAlign: 'start'
},
controls: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
},
nextPrevButton: {},
nextPrevButtonDisabled: { opacity: 0.3 },
pagination: {
display: 'flex'
},
paginationButton: {
margin: '10px'
},
paginationButtonActive: { opacity: 0.3 },
pageIndicator: {
display: 'flex',
justifyContent: 'center'
}
} satisfies Record;interface CarouselProps {
readonly items: T[];
readonly renderItem: (
props: CarouselRenderItemProps
) => React.ReactElement;
}interface CarouselRenderItemProps {
readonly item: T;
readonly isSnapPoint: boolean;
}export const Carousel = ({
items,
renderItem
}: CarouselProps) => {
const {
scrollRef,
pages,
activePageIndex,
hasPrevPage,
hasNextPage,
prev,
next,
goTo,
snapPointIndexes
} = useSnapCarousel();
return (
{items.map((item, i) =>
renderItem({
item,
isSnapPoint: snapPointIndexes.has(i)
})
)}
prev()}
disabled={!hasPrevPage}
>
Prev
{pages.map((_, i) => (
goTo(i)}
>
{i + 1}
))}
next()}
disabled={!hasNextPage}
>
Next
{activePageIndex + 1} / {pages.length}
);
};interface CarouselItemProps {
readonly isSnapPoint: boolean;
readonly children?: React.ReactNode;
}export const CarouselItem = ({ isSnapPoint, children }: CarouselItemProps) => (
{children}
);
```
```tsx
// App.tsx
import { Carousel, CarouselItem } from './Carousel';
const items = Array.from({ length: 20 }).map((_, i) => ({
id: i,
src: `https://picsum.photos/500?idx=${i}`
}));
const App = () => (
(
)}
/>
);
export default App;
```
## Api
### `useSnapCarousel(options)`
#### Parameters
##### Options
```ts
interface SnapCarouselOptions {
// Horizontal or vertical carousel
readonly axis?: 'x' | 'y';
// Allows you to render pagination during SSR
readonly initialPages?: number[][];
}
```
#### Return value
```ts
export interface SnapCarouselResult {
readonly pages: number[][];
readonly activePageIndex: number;
readonly snapPointIndexes: Set;
readonly hasPrevPage: boolean;
readonly hasNextPage: boolean;
readonly prev: (opts?: SnapCarouselGoToOptions) => void;
readonly next: (opts?: SnapCarouselGoToOptions) => void;
readonly goTo: (pageIndex: number, opts?: SnapCarouselGoToOptions) => void;
readonly refresh: () => void;
readonly scrollRef: (el: HTMLElement | null) => void;
}
```
## License
[MIT](LICENSE)