React Aria Carousel is a collection of React hooks and components that provide the behavior and accessibility implementation for building a carousel. Unlike many other carousels, this implementation uses the latest browser and DOM APIs for scrolling and snapping.
Features
Native browser scroll-snapping and smooth-scrolling for performant transitions across pointer types.
Comprehensive behavior and accessibility coverage for all elements of a carousel, including pagination, infinite scrolling, autoplay, and more.
Support for showing one or many items per page, implemented with responsive-design.
Support for vertical and horizontal scrolling.
Support for infinite scrolling.
Support for autoplay with affordances for disabling it.
Support for mouse dragging.
Written in TypeScript.
Installation
Usage
Anatomy
Carousels have a root element denoting the carousel region, which contains all of the different parts of the carousel, including the scrolling container, next and previous buttons, and optionally, tabs and the autoplay toggle.
Below is a simple example with minimal styles to show all of the different parts working together.
App.tsx
./styles.css
Multiple Items
The number of items present on a page can be changed with the itemsPerPage prop. You can change the spacing between items with the spaceBetweenItems prop.
1
2
3
4
5
6
App.tsx
./styles.module.css
Looping
By default, the carousel will not loop if one scrolls to either end. You can force the carousel to "wrap" in two different ways.
If the loop prop is set to "infinite", the carousel will give the appearance of seamlessly wrapping to the opposite end.
If the loop props is set to "native", the user still won't be able to scroll to the other end. However, the next and previous buttons and keyboard controls will scroll the user to the other end. ("Native" in this case means that the behavior of the scroll container aren't manipulated, it just provides the functionality to scroll the user to the other end.)
1
2
3
4
5
6
7
App.tsx
./styles.module.css
Orientation
By default, the carousel will scroll horizontally. This can be changed to scroll vertically with the orientation prop.
1
2
3
4
5
6
7
App.tsx
./styles.module.css
Mouse Dragging
The carousel uses CSS scroll snap to position slides at various snap positions. This allows users to scroll through the slides very naturally, especially on touch devices. Unfortunately, desktop users won’t be able to click and drag with a mouse, which can feel unnatural. The carousel provides this functionality with the mouseDragging prop.
This example is best demonstrated using a mouse. Try clicking and dragging the slide to move it.
1
2
3
4
5
6
7
App.tsx
./styles.module.css
Autoplay
Use the autoplay prop to automatically progress the carousel, dictated by the autoplayInterval prop. This functionality works great with the loop prop enabled. For best usability and accessibility, autoplay will pause if the user starts interacting with the carousel, and will resume when the stop interacting with it. Autoplay will also be disabled if the user's operating system or browser settings has the "prefers reduced motion" option enabled.
It's very important to include the CarouselAutoplayControl component when using this prop! Users must be able to disable this functionality.
1
2
3
4
5
6
7
App.tsx
./styles.module.css
Scroll Hints
The carousel has two different ways to hint to users that there are more items in the carousel.
The scrollPadding prop simply applies CSS scroll-padding to the scroll container. This has the effect of hinting the presence of items on either side of the carousel.
You can also manipulate the itemsPerPage prop to hint at more items. If you use a non-integer number, like 2.25, the carousel will show a quarter of the following item in the list. This option has the benefit of keeping the edges of the carousel nicely aligned to its container (as opposed to scrollPadding).
Scroll Padding
1
2
3
4
5
6
7
Fractional Items per Page
1
2
3
4
5
6
7
App.tsx
./styles.module.css
Accessibility & Labeling
React Aria Carousel includes most required labels and HTML semantics by default, but requires a label (via aria-label or aria-labelledby) for the Carousel component for it to properly be described by screen readers.
All other aria attributes and descriptions are provided in English. For non-English languages, they can be overridden. Here's an example of the component translated to Italian:
1
2
3
App.tsx
./styles.module.css
Note: translations may be innaccurate, I used Google Translate for them :).
Hooks
If you need to customize things even further, such as accessing internal state or customizing DOM structure, you can drop down to the lower level Hook-based API.
API
Carousel
The component accepts any valid HTML attributes, in addition to the following:
Name
Type
Default
Description
autoplay
boolean
false
If true, the carousel will scroll automatically when the user is not interacting with
autoplayInterval
number
5000
Specifies the amount of time, in milliseconds, between each automatic scroll.
children
ReactNode
-
The elements of the carousel.
initialPages
number[][]
[]
Define the organization of pages on first render. Useful to render navigation during SSR.
itemsPerPage
number
1
Number of items visible in a page. Can be an integer to show each item with equal dimensions, or a floating point number to "peek" subsequent items.
loop
'infinite' | 'native' | false
false
Controls the pagination behavior at the beginning and end.
mouseDragging
boolean
false
Controls whether the user can scroll by clicking and dragging with their mouse.
onActivePageIndexChange
(args: {index: number}) => void
-
Handler called when the activePageIndex changes.
orientation
'horizontal' | 'vertical'
'horizontal'
The carousel scroll direction
scollBy
'page' | 'item'
'page'
Controls whether scrolling snaps and pagination progresses by item or page.
scrollPadding
string
-
The amount of padding to apply to the scroll area, allowing adjacent items to become partially visible.
spaceBetweenItems
string
'0px'
The gap between items.
CarouselScroller
The component accepts any valid HTML attributes, in addition to the following:
If true, the carousel will scroll automatically when the user is not interacting with
autoplayInterval
number
5000
Specifies the amount of time, in milliseconds, between each automatic scroll.
initialPages
number[][]
[]
Define the organization of pages on first render. Useful to render navigation during SSR.
itemsPerPage
number
1
Number of items visible in a page. Can be an integer to show each item with equal dimensions, or a floating point number to "peek" subsequent items.
loop
'infinite' | 'native' | false
false
Controls the pagination behavior at the beginning and end.
mouseDragging
boolean
false
Controls whether the user can scroll by clicking and dragging with their mouse.
onActivePageIndexChange
(args: {index: number}) => void
-
Handler called when the activePageIndex changes.
orientation
'horizontal' | 'vertical'
'horizontal'
The carousel scroll direction
scollBy
'page' | 'item'
'page'
Controls whether scrolling snaps and pagination progresses by item or page.
scrollPadding
string
-
The amount of padding to apply to the scroll area, allowing adjacent items to become partially visible.
spaceBetweenItems
string
'0px'
The gap between items.
useCarouselItem
Name
Type
Default
Description
item
Item<T>
-
An item in the collection of carousel items.
useCarouselTab
Name
Type
Default
Description
index
number
-
An index of a page in the carousel.
isSelected
boolean
-
Whether the page is the active, visible page of the carousel.
Browser Support
A goal of this project is to use modern browser technology. While most APIs are widely supported, the scrollend notably is not supported in Safari (as of May 2024). A polyfill is not included to future-proof the project, but you will likely want to include one.
Acknowledgements
react-snap-carousel is another DOM-first, headless carousel for React that was a big insipiration for this project. It's less opinionated about the layout of the carousel (i.e., does not require CSS grid).
Shoelace carousel is a Web Component implementation for a DOM-first carousel, that can also be used in React. It's a bit more opinionated about the HTML layout and presentation of the carousel.
Blog posts and resources used to inform the accessibility implementation: