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' });
 
return (
    <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 manages scroll snapping, swipe gestures, and page tracking for a content slider — see Primitive for a component-based API.

Features#

  • Returns spread-ready prop objects (rootProps, contentProps, getItemProps, getNextProps, getPrevProps, indicatorsProps, getIndicatorProps)
  • CSS scroll-snap based navigation with configurable snap type
  • Mouse swipe gestures via PointerEvent with automatic snap-to-closest
  • IntersectionObserver-driven data-inview attribute on items
  • Imperative methods: next(), prev(), scrollToPage(), scrollToSlide()
  • Exposes state.page, state.swiping, state.isPrevDisabled, state.isNextDisabled, state.snapPoints

Behavior#

Default Page#

Set defaultPage to start on a specific page index.

const carousel = useCarousel({ defaultPage: 2 });

Controlled Page#

Use page and onPageChange for full programmatic control over the current page.

const [page, setPage] = React.useState(0);
const carousel = useCarousel({
    page,
    onPageChange: (e) => setPage(e.value)
});

Controlled Slide#

Use slide and onSlideChange to control by item index rather than page index. This is useful for gallery-style carousels where each item maps 1:1 to a page.

const [slide, setSlide] = React.useState(0);
const carousel = useCarousel({
    slide,
    onSlideChange: (e) => setSlide(e.value)
});

Alignment#

Set align to 'start', 'center', or 'end' to control how items snap within the viewport.

const carousel = useCarousel({ align: 'start' });

Slides Per Page#

Set slidesPerPage to control the number of visible items. Fractional values like 1.5 show partial items to hint at more content.

const carousel = useCarousel({ slidesPerPage: 1.5, align: 'start' });

Orientation#

Set orientation to 'vertical' for a vertical carousel.

const carousel = useCarousel({ orientation: 'vertical' });

Loop#

Set loop to enable infinite navigation. Navigation buttons are never disabled in loop mode.

const carousel = useCarousel({ loop: true });

Variable Size#

Set autoSize to allow items with different widths. Items use their natural size instead of calculating from slidesPerPage.

const carousel = useCarousel({ autoSize: true });

Spacing#

Set spacing to define the gap between items in pixels.

const carousel = useCarousel({ spacing: 24 });

Using state.page and state.swiping#

The hook exposes reactive state for custom UI logic.

const carousel = useCarousel();
 
<span>Page {carousel.state.page + 1}</span>;
{
    carousel.state.swiping && <span>Swiping...</span>;
}

CSS Custom Properties#

contentProps.style sets three CSS custom properties on the content element. These can be consumed in item sizing and layout calculations.

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(--slides-per-page) - var(--spacing-items) * (var(--slides-per-page) - 1) / var(--slides-per-page));
}

Custom Styling with Data Attributes#

Prop objects include orientation and state-dependent data attributes.

[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#

See Carousel Primitive for WAI-ARIA compliance details and keyboard support.