Carousel
One carousel for single slides, responsive multi-slide tracks, a continuous ticker, and a 3D coverflow. Transform-based slides, progress dots, seamless looping, swipe, and keyboard support, with no external dependency. Autoplay is opt-in.
Basic autoplay
Autoplay is opt-in: pass autoplay to advance every 3000ms with no arrows. The active dot fills to show progress until the next slide.
- autoplay defaults to false - self-starting motion is the page owner's WCAG 2.2.2 obligation
- Autoplay pauses on hover, focus, touch, and when the tab is hidden, and never runs under prefers-reduced-motion
Configurable interval
Pass autoplay with autoplayInterval; the progress dot animation matches it.
Transition duration
transitionDuration sets how long each move takes, in milliseconds. Raised close to autoplayInterval, the track glides almost continuously instead of stepping and then pausing.
- Defaults to the shared --fuji-duration-slow token
Arrow controls
Pass controls for prev/next arrows overlaid on the edges. The arrows are icon buttons on a translucent disc, so they read over any photo, and the indicator dots are 24px hit targets.
Non-looping edges
With loop set to false, the arrows disable themselves at the first and last slide.
Responsive multi-image
slidesPerView takes a responsive map. Slide count changes at CSS breakpoints, not via JavaScript.
Infinite autoplay, multiple cards
Use continuous mode for a smooth, always-moving image track with responsive card widths. It pauses while hovered or focused and has no arrows or bottom indicators.
Coverflow effect
effect='coverflow' centers the active slide with neighbours rotated away in 3D and scaled by distance; the fan follows the pointer while dragging and snaps on release. Arrow keys and controls work as in the default preset; slidesPerView is ignored.
- Coverflow ignores slidesPerView - the active slide is always centered with its neighbours fanned behind it
Controlled index
Drive the active slide from your own state with index and onIndexChange.
- The track is a labeled region; ArrowLeft and ArrowRight move between slides when it has focus.
- Each slide is labeled "Slide N of total", and clone slides used for looping are hidden from assistive tech.
- Autoplay and slide transitions are disabled under prefers-reduced-motion.
- An imperative handle exposes next, previous, and goTo through a ref.
When to use
- A small set of visually equivalent items where showing one (or a few) at a time saves space - featured content, a product gallery, a testimonial rotation.
- Content the user doesn't need all of at once, and can miss slides of without losing anything essential.
When not to use
- Content that's actually important for every visitor to see - carousels have well-documented low interaction rates; don't hide primary CTAs or key information behind autoplay.
- Long lists better served by a Grid or scrollable list where everything is visible/scannable at once.
- A step-by-step flow - use Stepper or Tabs, which better communicate sequence and progress.
Keyboard
Mobile behavior
- swipe (default true) enables touch/pointer dragging between slides - this is the primary interaction on touch devices, not a bonus on top of arrow controls.
- controls (prev/next arrow buttons) default to off - enable them explicitly if touch swipe alone isn't enough for your audience.
- Slides that are images or links swipe like any other: the carousel cancels the browser's native drag on its viewport. Give a child its own draggable to opt back in.
Accessibility notes
- Autoplay automatically pauses on hover, focus, touch, and when the browser tab is hidden - and never runs at all under prefers-reduced-motion.
- Each slide announces as "Slide N of total" to screen readers; clone slides used to fake seamless looping are hidden from assistive tech (aria-hidden) so they never get double-announced.
- The track itself is a labeled region so ArrowLeft/ArrowRight navigation is discoverable once focused.
Common mistakes
- Putting the only copy of important information in slide 2+ of an autoplaying carousel - most users never see past the first slide.
- Leaving autoplay on for content-heavy slides (long text, forms) - autoplay is for glanceable content, not anything requiring reading time.
- Disabling swipe on mobile without providing visible arrow controls instead - that leaves touch users with no way to advance.
Known limitations
- No built-in lazy-loading of off-screen slide images - pair with the Image component's own loading behavior and set `loading="eager"` only for the first visible slide(s).
API reference
The slides. Each child becomes one slide.
Defines a string value that labels the current element.
Advance automatically; paused on hover/focus/touch/tab-hidden, off under reduced motion. Defaults to **false** (since 0.3.0): self-starting motion over 5s is a WCAG 2.2.2 duty, so it's opt-in.
Milliseconds between autoplay advances. Default 3000.
Always-moving CSS marquee instead of stepped slides; only `autoplayInterval` (ms per slide-width) and `slidesPerView` apply. Pauses on hover/focus, tab-hidden and reduced motion. Default false.
Overlay prev/next arrow controls. Default false.
Uncontrolled initial index. Default 0.
`"coverflow"` ports motion.dev's: a centred ~62% slide, neighbours rotated 20° and shrunk to 70%, faded edges, following the drag then snapping. Default `"slide"`.
Controlled active slide index.
Bottom dot indicators. Default true.
Wrap seamlessly past the ends. Default true.
Called with the new index whenever the active slide changes, however it changed.
Slides per view: a number or breakpoint map. Default 1 - or 1.6 with `effect="coverflow"`, where it sets the centre width (`100% / slidesPerView`; 1.6 is ~62%, 3 shows more fan; min 1).
Allow touch/pointer swiping. Default true.
Per-slide transition length in ms. Defaults to the shared `--fuji-duration-slow` token. Raise it towards `autoplayInterval` for a continuous glide instead of a quick step and a long pause.
Also accepts everything from Omit<React.HTMLAttributes<HTMLDivElement>, "onChange">.
Coding agents read this reference, with its examples, from the version your project has installed, through the Fuji UI MCP server. Set up your agent
