Carousel
React carousel component with touch gestures, keyboard navigation, and smooth animations. Perfect for image galleries, product showcases, and content sliders.
Need to showcase multiple items in limited space? Users expect smooth swipe gestures and intuitive navigation. The Carousel component handles everything from product galleries to testimonial sliders with professional animations and accessibility.
Built on Embla Carousel with full touch support, keyboard navigation, and customizable layouts that work on every device.
npx shadcn@latest add carousel
Why carousels work so well
Users understand carousel patterns from everywhere - phones, tablets, websites:
- Touch and swipe gestures - Natural finger movements on mobile devices
- Keyboard navigation - Arrow keys work exactly as expected
- Visual navigation - Previous/next buttons and dot indicators
- Smooth animations - Professional transitions between slides
- Responsive layouts - Adapts perfectly to any screen size
- Screen reader friendly - Proper ARIA labels and roles
- Memory efficient - Only renders visible slides plus buffer
Common carousel patterns you'll build
Different slide sizes per screen
Show more items on larger screens, fewer on mobile:
Custom spacing between slides
Control the gap between carousel items:
Vertical scrolling carousels
Perfect for timelines, testimonials, or compact layouts:
Advanced configuration options
Loop infinitely, align to start, or customize behavior:
Programmatic control and state
Get current slide, total count, and control navigation:
Auto-play and plugins
Add automatic sliding with customizable timing:
API Reference
Carousel
The root carousel component that provides context and manages the Embla Carousel instance.
Prop | Type | Default | Description |
---|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" | The orientation of the carousel |
opts | EmblaOptionsType | - | Embla Carousel options for behavior and layout |
plugins | EmblaPluginType[] | - | Array of Embla Carousel plugins to extend functionality |
setApi | (api: CarouselApi) => void | - | Callback to get the carousel API instance for programmatic control |
className | string | - | Additional CSS classes for the carousel container |
children | React.ReactNode | - | Carousel content including CarouselContent and navigation buttons |
CarouselContent
The scrollable container that holds all carousel items.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes (commonly used for negative margins for spacing) |
children | React.ReactNode | - | CarouselItem components |
CarouselItem
Individual slide wrapper that contains your content.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes (commonly used for basis and padding) |
children | React.ReactNode | - | The content for this carousel slide |
CarouselPrevious
Navigate to the previous slide. Automatically disables when at the first slide.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes for styling and positioning |
variant | ButtonVariant | "outline" | Button appearance variant |
size | ButtonSize | "icon" | Button size |
onClick | () => void | - | Additional click handler (carousel navigation is automatic) |
CarouselNext
Navigate to the next slide. Automatically disables when at the last slide.
Prop | Type | Default | Description |
---|---|---|---|
className | string | - | Additional CSS classes for styling and positioning |
variant | ButtonVariant | "outline" | Button appearance variant |
size | ButtonSize | "icon" | Button size |
onClick | () => void | - | Additional click handler (carousel navigation is automatic) |
Common Embla Options
The opts
prop accepts Embla Carousel configuration:
Option | Type | Default | Description |
---|---|---|---|
align | "start" | "center" | "end" | "center" | How slides align within the viewport |
loop | boolean | false | Enable infinite loop scrolling |
skipSnaps | boolean | false | Allow scrolling past snap points |
dragFree | boolean | false | Enable free-scroll without snap points |
slidesToScroll | number | "auto" | 1 | Number of slides to scroll at once |
duration | number | 25 | Animation duration in frames |
startIndex | number | 0 | Initial slide index |
CarouselApi Methods
When using setApi
, you get access to these methods:
Method | Description |
---|---|
scrollNext() | Navigate to next slide |
scrollPrev() | Navigate to previous slide |
scrollTo(index) | Navigate to specific slide by index |
canScrollNext() | Check if can scroll to next slide |
canScrollPrev() | Check if can scroll to previous slide |
selectedScrollSnap() | Get current slide index |
scrollSnapList() | Get array of all slide positions |
on(event, callback) | Listen to carousel events |
off(event, callback) | Remove event listener |
Keyboard Navigation
Key | Description |
---|---|
ArrowLeft | Previous slide (horizontal) |
ArrowRight | Next slide (horizontal) |
ArrowUp | Previous slide (vertical) |
ArrowDown | Next slide (vertical) |
Home | First slide |
End | Last slide |
Carousel best practices
What makes carousels feel smooth and professional:
- Show partial next slide - Give users a hint that more content exists
- Consistent item sizes - Avoid jarring layout shifts between slides
- Reasonable auto-play timing - 4-5 seconds gives users time to read
- Pause on hover - Let users stop auto-play when they're interested
- Progress indicators - Help users understand their position
- Touch-friendly spacing - Buttons and swipe areas work well on mobile
- Keyboard navigation - Arrow keys should always work
- Performance-first - Lazy load images and clean up event listeners