Introducing PrimeReact v11-alpha 🎉Discover Now

useCarousel

Hook that manages carousel scroll snapping, swipe gestures, and page-based navigation.

1
2
3
4
5
basic-demo

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 scrollToPage and scrollToSlide
  • Responsive visibility — slidesPerPage accepts fractional values (e.g. 1.5) to hint at off-screen content
  • Intersection tracking — data-inview updates 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:

VariableDescription
--slides-per-pageNumber of visible slides per page, derived from slidesPerPage.
--spacing-itemsGap between items in pixels, derived from spacing.
--scroll-snap-typeResolved 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#

NameTypeDefault
autoSizebooleanfalse
Whether the carousel should auto size.
orientation"horizontal" | "vertical"'horizontal'
Orientation of the carousel.
align"center" | "start" | "end"'center'
Alignment of the carousel items.
loopbooleanfalse
Whether the carousel should loop.
snapType"mandatory" | "proximity"'mandatory'
Scroll snap type applied to the track.
spacingnumber16
Spacing between carousel items.
slidesPerPagenumber1
How many slides are visible per page. Supports fractions (e.g. 1.5).
pagenumberundefined
Index of the active slide.
slidenumberundefined
Index of the active slide.
defaultPagenumber0
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.