Skip to main content

Installation

npx shadcn@latest add carousel

Usage

import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/ui/carousel"
<Carousel>
  <CarouselContent>
    <CarouselItem>Item 1</CarouselItem>
    <CarouselItem>Item 2</CarouselItem>
    <CarouselItem>Item 3</CarouselItem>
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Component Code

The Carousel component is built on top of embla-carousel-react.
"use client"

import * as React from "react"
import useEmblaCarousel, { type UseEmblaCarouselType } from "embla-carousel-react"
import { ArrowLeft, ArrowRight } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"

type CarouselApi = UseEmblaCarouselType[1]
type CarouselOptions = Parameters<typeof useEmblaCarousel>[0]
type CarouselPlugin = Parameters<typeof useEmblaCarousel>[1]

type CarouselProps = {
  opts?: CarouselOptions
  plugins?: CarouselPlugin
  orientation?: "horizontal" | "vertical"
  setApi?: (api: CarouselApi) => void
}

function Carousel({
  orientation = "horizontal",
  opts,
  setApi,
  plugins,
  className,
  children,
  ...props
}: React.ComponentProps<"div"> & CarouselProps) {
  const [carouselRef, api] = useEmblaCarousel(
    {
      ...opts,
      axis: orientation === "horizontal" ? "x" : "y",
    },
    plugins
  )
  
  // ... implementation details
  
  return (
    <div
      data-slot="carousel"
      className={cn("relative", className)}
      role="region"
      aria-roledescription="carousel"
      {...props}
    >
      {children}
    </div>
  )
}

function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div className="overflow-hidden" data-slot="carousel-content">
      <div
        className={cn("flex", className)}
        {...props}
      />
    </div>
  )
}

function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      role="group"
      aria-roledescription="slide"
      data-slot="carousel-item"
      className={cn("min-w-0 shrink-0 grow-0 basis-full", className)}
      {...props}
    />
  )
}

export { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious }

Examples

A basic carousel with navigation buttons.
<Carousel className="w-full max-w-xs">
  <CarouselContent>
    <CarouselItem>
      <Card>
        <CardContent className="flex aspect-square items-center justify-center p-6">
          <span className="text-4xl font-semibold">1</span>
        </CardContent>
      </Card>
    </CarouselItem>
    <CarouselItem>
      <Card>
        <CardContent className="flex aspect-square items-center justify-center p-6">
          <span className="text-4xl font-semibold">2</span>
        </CardContent>
      </Card>
    </CarouselItem>
    <CarouselItem>
      <Card>
        <CardContent className="flex aspect-square items-center justify-center p-6">
          <span className="text-4xl font-semibold">3</span>
        </CardContent>
      </Card>
    </CarouselItem>
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Plugins

The Carousel component supports Embla Carousel plugins. For example, to add autoplay:
import Autoplay from "embla-carousel-autoplay"

<Carousel
  plugins={[
    Autoplay({
      delay: 2000,
    }),
  ]}
>
  {/* content */}
</Carousel>

API Reference

PropTypeDefault
orientation"horizontal" | "vertical""horizontal"
optsCarouselOptions-
pluginsCarouselPlugin[]-
setApi(api: CarouselApi) => void-
classNamestring-
For more options, see the Embla Carousel documentation.

CarouselContent

PropTypeDefault
classNamestring-

CarouselItem

PropTypeDefault
classNamestring-

CarouselPrevious / CarouselNext

PropTypeDefault
variantButton variant"outline"
sizeButton size"icon"
classNamestring-

Build docs developers (and LLMs) love