Carousel

A flexible, accessible carousel component powered by Embla Carousel.

Quick Start

Use Carousel to display content in a horizontally or vertically scrollable viewport.

Slide 1

Slide 2

Slide 3

1<Carousel>
2  <CarouselContent>
3    <CarouselItem>
4      Slide 1
5    </CarouselItem>
6
7    <CarouselItem>
8      Slide 2
9    </CarouselItem>
10
11    <CarouselItem>
12      Slide 3
13    </CarouselItem>
14  </CarouselContent>
15
16  <CarouselPrevious />
17  <CarouselNext />
18</Carousel>

The default carousel scrolls horizontally and displays one slide per view.

Slide 1
Slide 2
Slide 3
1<Carousel>
2  <CarouselContent>
3    <CarouselItem>
4      Slide 1
5    </CarouselItem>
6
7    <CarouselItem>
8      Slide 2
9    </CarouselItem>
10
11    <CarouselItem>
12      Slide 3
13    </CarouselItem>
14  </CarouselContent>
15
16  <CarouselPrevious />
17  <CarouselNext />
18</Carousel>

Multiple Items Per View

Use custom slide widths alongside Embla options to display multiple items.

Card 1
Card 2
Card 3
Card 4
Card 5
Card 6
1<Carousel
2  opts={{
3    align: "start",
4  }}
5>
6  <CarouselContent>
7    {items.map((item) => (
8      <CarouselItem
9        key={item.id}
10        className="basis-full sm:basis-1/2 lg:basis-1/3"
11      >
12        {item.content}
13      </CarouselItem>
14    ))}
15  </CarouselContent>
16
17  <CarouselPrevious />
18  <CarouselNext />
19</Carousel>

Use the orientation prop to scroll content vertically.

Slide 1
Slide 2
Slide 3
1<Carousel
2  orientation="vertical"
3  className="max-w-md"
4>
5  <CarouselContent className="h-[300px]">
6    {[1, 2, 3].map((item) => (
7      <CarouselItem key={item}>
8        <div className="flex h-[300px] items-center justify-center rounded-md border">
9          Slide {item}
10        </div>
11      </CarouselItem>
12    ))}
13  </CarouselContent>
14
15  <CarouselPrevious />
16  <CarouselNext />
17</Carousel>

Plugins

Embla plugins can be supplied using the plugins prop. See the Embla documentation for the full list of supported plugins.

1<Carousel
2  plugins={[
3    Autoplay({
4      delay: 3000,
5    }),
6  ]}
7>
8  <CarouselContent>
9    <CarouselItem>
10      Slide 1
11    </CarouselItem>
12
13    <CarouselItem>
14      Slide 2
15    </CarouselItem>
16
17    <CarouselItem>
18      Slide 3
19    </CarouselItem>
20  </CarouselContent>
21</Carousel>

Access the Embla API using the setApi prop to build custom carousel experiences.

1function Example() {
2  const [api, setApi] = useState<CarouselApi>();
3  const [current, setCurrent] = useState(1);
4  const [count, setCount] = useState(0);
5
6  React.useEffect(() => {
7    if (!api) return;
8
9    setCount(
10      api.scrollSnapList().length
11    );
12
13    setCurrent(
14      api.selectedScrollSnap() + 1
15    );
16
17    api.on("select", () => {
18      setCurrent(
19        api.selectedScrollSnap() + 1
20      );
21    });
22  }, [api]);
23
24  return (
25    <>
26      <Carousel setApi={setApi}>
27        <CarouselContent>
28          ...
29        </CarouselContent>
30      </Carousel>
31
32      <div>
33        Slide {current} of {count}
34      </div>
35    </>
36  );
37}

Use the useCarouselNavButtons hook to build custom slide indicators.

1function Example() {
2  const [api, setApi] = useState<CarouselApi>();
3
4  const {
5    selectedIndex,
6    scrollSnaps,
7    onCarouselNavButtonClick,
8  } = useCarouselNavButtons(api);
9
10  return (
11    <>
12      <Carousel setApi={setApi}>
13        <CarouselContent>
14          ...
15        </CarouselContent>
16      </Carousel>
17
18      <div>
19        {scrollSnaps.map(
20          (_, index) => (
21            <button
22              key={index}
23              onClick={() =>
24                onCarouselNavButtonClick(
25                  index
26                )
27              }
28            >
29              {index + 1}
30            </button>
31          )
32        )}
33      </div>
34    </>
35  );
36}

Custom Embla Options

Pass any supported Embla options using the opts prop. See the Embla documentation for the full list of supported options.

Slide 1
Slide 2
Slide 3
1<Carousel
2  opts={{
3    loop: true,
4    align: "center",
5    dragFree: true,
6  }}
7>
8  <CarouselContent>
9    ...
10  </CarouselContent>
11</Carousel>

API Reference

Property

Type

Default

Description

orientation"horizontal" | "vertical""horizontal"Controls the carousel scroll direction.
optsCarouselOptions-Embla carousel configuration options.
pluginsCarouselPlugin[]-Collection of Embla plugins to apply.
setApi(api: CarouselApi) => void-Provides access to the underlying Embla API instance.
classNamestring-Additional classes applied to the root element.

CarouselContent

Property

Type

Default

Description

classNamestring-Additional classes applied to the content container.
childrenReactNode-Collection of carousel items.

CarouselItem

Property

Type

Default

Description

classNamestring-Additional classes applied to the slide element.
childrenReactNode-Content rendered within the slide.

CarouselPrevious

Property

Type

Default

Description

variantButtonVariant"default"Button variant used for the navigation control.
sizeButtonSize"icon"Button size used for the navigation control.

CarouselNext

Property

Type

Default

Description

variantButtonVariant"default"Button variant used for the navigation control.
sizeButtonSize"icon"Button size used for the navigation control.

useCarouselNavButtons

Property

Type

Default

Description

emblaApiCarouselApi | undefined-The carousel API instance returned via setApi.

Visual Reference

Configuration

Preview

Default
Horizontal 1
Horizontal 2
Multiple Items
A
B
C
Loop
Loop 1
Loop 2
Vertical
Vertical 1
Vertical 2