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 |
|---|---|---|
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.