Docs
Carousel

Carousel

A versatile carousel component featuring smooth motion, touch/swipe interactions, and customizable options, built upon the performant Embla Carousel library.

Loading...

About

This carousel component leverages the powerful and lightweight Embla Carousel library. Embla Carousel is chosen for its performance, flexibility, and framework-agnostic nature, providing a solid foundation for creating smooth, touch-friendly carousels. It handles the core mechanics of sliding, swiping, and responsiveness, allowing us to build upon it with custom styling and features.

Installation

npx shadcn@latest add carousel

Usage

  Carousel, // Main wrapper component for the carousel functionality.
  CarouselContent, // Container for the carousel items. Handles the sliding track.
  CarouselItem, // Individual item within the carousel. Each child here is a slide.
  CarouselNext, // Button to navigate to the next slide.
  CarouselPrevious, // Button to navigate to the previous slide.
} from "@/components/ui/carousel";
<Carousel>
  <CarouselContent>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Examples

Sizes

Control the visible number of items or their individual widths using Flexbox utility classes directly on the <CarouselItem /> component. The basis-* utility (e.g., basis-1/3) sets the initial main size of a flex item. This allows you to define how much space each item should occupy within the <CarouselContent /> container. You can also use responsive prefixes (like md:basis-1/2) to adjust item sizes based on screen dimensions.

Loading...
// 33% of the carousel width.
<Carousel>
  <CarouselContent>
    <CarouselItem className="basis-1/3">...</CarouselItem>
    <CarouselItem className="basis-1/3">...</CarouselItem>
    <CarouselItem className="basis-1/3">...</CarouselItem>
  </CarouselContent>
</Carousel>
// 50% on small screens and 33% on larger screens.
<Carousel>
  <CarouselContent>
    <CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
    <CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
    <CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
  </CarouselContent>
</Carousel>

Spacing

Achieve spacing between carousel items using a combination of padding and negative margin utilities. Apply padding (e.g., pl-4) to the <CarouselItem /> to create space on one side, and then apply a corresponding negative margin (e.g., -ml-4) to the <CarouselContent /> container. This technique effectively pulls the content container back to counteract the added padding on the first item, ensuring consistent spacing without relying on the gap property, which can sometimes complicate calculations with dynamic item widths.

Loading...
<Carousel>
  <CarouselContent className="-ml-4">
    <CarouselItem className="pl-4">...</CarouselItem>
    <CarouselItem className="pl-4">...</CarouselItem>
    <CarouselItem className="pl-4">...</CarouselItem>
  </CarouselContent>
</Carousel>
<Carousel>
  <CarouselContent className="-ml-2 md:-ml-4">
    <CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
    <CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
    <CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
  </CarouselContent>
</Carousel>

Orientation

The carousel can be displayed horizontally (default) or vertically. Set the orientation prop on the main <Carousel /> component to "vertical" to switch the sliding direction. Vertical carousels might be suitable for specific layouts or content types where vertical scrolling is more natural. Ensure your item styling accommodates the vertical flow.

Loading...
<Carousel orientation="vertical | horizontal">
  <CarouselContent>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
  </CarouselContent>
</Carousel>

Options

Customize the behavior of the underlying Embla Carousel instance by passing an options object to the opts prop on the <Carousel /> component. This allows fine-grained control over aspects like alignment (align), looping behavior (loop), initial slide index (startIndex), drag sensitivity (dragFree), and more. Refer to the official Embla Carousel Options API documentation for a complete list of available options and their effects.

<Carousel
  opts={{
    align: "start",
    loop: true,
  }}
>
  <CarouselContent>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
  </CarouselContent>
</Carousel>

API

For advanced control and interaction, you can access the Embla Carousel API instance. Pass a state setter function (like setApi from React.useState) to the setApi prop on the <Carousel /> component. Once the carousel is initialized, this function will be called with the API instance. You can then use this API object to programmatically scroll to specific slides (scrollTo), get information about the current state (e.g., selectedScrollSnap, scrollSnapList), reinitialize the carousel (reInit), and more. This is useful for building custom controls, synchronizing the carousel with other UI elements (like pagination dots), or reacting to its state changes.

Loading...
import { type CarouselApi } from "@/components/ui/carousel";

export function Example() {
  const [api, setApi] = React.useState<CarouselApi>();
  const [current, setCurrent] = React.useState(0);
  const [count, setCount] = React.useState(0);

  React.useEffect(() => {
    if (!api) {
      return;
    }

    setCount(api.scrollSnapList().length);
    setCurrent(api.selectedScrollSnap() + 1);

    api.on("select", () => {
      setCurrent(api.selectedScrollSnap() + 1);
    });
  }, [api]);

  return (
    <Carousel setApi={setApi}>
      <CarouselContent>
        <CarouselItem>...</CarouselItem>
        <CarouselItem>...</CarouselItem>
        <CarouselItem>...</CarouselItem>
      </CarouselContent>
    </Carousel>
  );
}

Events

Respond to user interactions and state changes within the carousel by attaching event listeners to the API instance obtained via the setApi prop. Embla Carousel emits various events such as select (when a slide is selected), scroll (during scrolling), resize (when the carousel resizes), and destroy (when the carousel is unmounted). Use the api.on('eventName', callback) method to register listeners and api.off('eventName', callback) to remove them. This enables you to trigger side effects, update related UI components, or perform actions based on the carousel's lifecycle and user activity. Consult the Embla Carousel Events API documentation for details on all available events.

import { type CarouselApi } from "@/components/ui/carousel";

export function Example() {
  const [api, setApi] = React.useState<CarouselApi>();

  React.useEffect(() => {
    if (!api) {
      return;
    }

    api.on("select", () => {
      // Do something on select.
    });
  }, [api]);

  return (
    <Carousel setApi={setApi}>
      <CarouselContent>
        <CarouselItem>...</CarouselItem>
        <CarouselItem>...</CarouselItem>
        <CarouselItem>...</CarouselItem>
      </CarouselContent>
    </Carousel>
  );
}

See the Embla Carousel docs for more information on using events.

Plugins

Extend the core functionality of the carousel by adding Embla Carousel plugins. Pass an array of initialized plugins to the plugins prop on the <Carousel /> component. Plugins can introduce features like autoplay (Autoplay), parallax effects, fade transitions, or custom navigation elements. You typically import the plugin, instantiate it (often with configuration options), and include it in the plugins array. Explore the official Embla Carousel Plugins documentation and community plugins to discover available extensions.

import Autoplay from "embla-carousel-autoplay"

export function Example() {
  return (
    <Carousel
      plugins={[
        Autoplay({
          delay: 2000,
        }),
      ]}
    >
      // ...
    </Carousel>
  )
}
Loading...

See the Embla Carousel docs for more information on using plugins.

    Carousel