useCarousel
Hook that manages carousel scroll snapping, swipe gestures, and page-based navigation.
Usage#
import { useCarousel } from '@primereact/headless/carousel';const carousel = useCarousel({ align: 'center' });
<div {...carousel.rootProps}>
<div ref={carousel.contentRef} {...carousel.contentProps}>
<div {...carousel.getItemProps(0)}></div>
</div>
<div {...carousel.indicatorsProps}>
<button {...carousel.getIndicatorProps(0)}></button>
</div>
<button {...carousel.getPrevProps(carousel.state.isPrevDisabled)}></button>
<button {...carousel.getNextProps(carousel.state.isNextDisabled)}></button>
</div>;useCarousel wires scroll snapping, swipe gestures, and page tracking together for a content slider. See Primitive for a component-based API.
Features#
- Scroll-snap navigation — CSS scroll-snap drives the layout, so native momentum, wheel, and touch gestures work out of the box
- Swipe gestures — pointer-based dragging with auto snap-to-closest when the drag releases
- Page and slide addressing — navigate by page index or by a specific slide with
scrollToPageandscrollToSlide - Responsive visibility —
slidesPerPageaccepts fractional values (e.g.1.5) to hint at off-screen content - Intersection tracking —
data-inviewupdates on each item as it enters or leaves the viewport - Configurable layout — orientation, alignment, spacing, auto-size, and loop modes all expose reactive state
Working with callbacks#
onPageChange — controlled navigation#
Pair page with onPageChange when navigation must be driven from parent state, hash routing, or analytics hooks.
const [page, setPage] = React.useState(0);
const carousel = useCarousel({
page,
onPageChange: (e) => setPage(e.value)
});Slide-indexed control#
Use slide / onSlideChange for gallery-style carousels where every item is one page.
const [slide, setSlide] = React.useState(0);
const carousel = useCarousel({
slide,
onSlideChange: (e) => setSlide(e.value)
});Peek layouts with fractional slides#
Combine slidesPerPage with align: 'start' to show a peek of the next slide — a common mobile pattern.
const carousel = useCarousel({ slidesPerPage: 1.5, align: 'start', spacing: 16 });Infinite loop navigation#
Enable loop so the prev/next props never disable and navigation wraps at the boundaries.
const carousel = useCarousel({ loop: true });Rendering custom indicators#
Read state.page and state.snapPoints to draw progress bars, fractions, or dot indicators without extra calculations.
const carousel = useCarousel();
<span>
{carousel.state.page + 1} / {carousel.state.snapPoints.length}
</span>;Styling with data attributes#
Prop objects include orientation and state-dependent data attributes. contentProps.style also exposes the following CSS custom properties:
| Variable | Description |
|---|---|
--slides-per-page | Number of visible slides per page, derived from slidesPerPage. |
--spacing-items | Gap between items in pixels, derived from spacing. |
--scroll-snap-type | Resolved scroll-snap-type value (e.g. x mandatory). |
[data-scope='carousel'][data-part='item'] {
flex-basis: calc(100% / var(--px-slides-per-page) - var(--px-spacing-items) * (var(--px-slides-per-page) - 1) / var(--px-slides-per-page));
}
[data-scope='carousel'][data-part='content'][data-orientation='horizontal'] {
overflow-x: scroll;
}
[data-scope='carousel'][data-part='content'][data-orientation='vertical'] {
flex-direction: column;
overflow-y: scroll;
}
[data-scope='carousel'][data-part='item'][data-inview] {
opacity: 1;
}
[data-scope='carousel'][data-part='indicator'][data-active] {
background: var(--primary);
}API#
useCarousel#
| Name | Type | Default |
|---|---|---|
autoSize | boolean | false |
| Whether the carousel should auto size. | ||
orientation | "horizontal" | "vertical" | 'horizontal' |
| Orientation of the carousel. | ||
align | "center" | "start" | "end" | 'center' |
| Alignment of the carousel items. | ||
loop | boolean | false |
| Whether the carousel should loop. | ||
snapType | "mandatory" | "proximity" | 'mandatory' |
| Scroll snap type applied to the track. | ||
spacing | number | 16 |
| Spacing between carousel items. | ||
slidesPerPage | number | 1 |
| How many slides are visible per page. Supports fractions (e.g. 1.5). | ||
page | number | undefined |
| Index of the active slide. | ||
slide | number | undefined |
| Index of the active slide. | ||
defaultPage | number | 0 |
| Default index of the active slide. | ||
onPageChange | (event: useCarouselChangeEvent) => void | — |
| Callback fired when the carousel's page changes. | ||
onSlideChange | (event: useCarouselChangeEvent) => void | — |
| Callback fired when the active slide (by value) changes. | ||
Accessibility#
Arrow keys move between slides, Home/End jump to first/last, and Space or Enter pauses autoplay. See Primitive for full WAI-ARIA compliance details.