# Carousel

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
---

<Carousel opts={{ align: "start" }} class="mx-auto w-full max-w-xs">
  <CarouselContent>
    {
      Array.from({ length: 5 }).map((_, index) => (
        <CarouselItem>
          <div class="p-1">
            <Card>
              <CardContent class="flex aspect-square items-center justify-center p-6">
                <span class="text-4xl font-semibold">{index + 1}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      ))
    }
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>
```
  </div>
  <div slot="react">
```tsx
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";

export function Example() {
  return (
    <Carousel opts={{ align: "start" }} className="mx-auto w-full max-w-xs">
      <CarouselContent>
        {
          Array.from({ length: 5 }).map((_, index) => (
            <CarouselItem key={index}>
              <div className="p-1">
                <Card>
                  <CardContent className="flex aspect-square items-center justify-center p-6">
                    <span className="text-4xl font-semibold">{index + 1}</span>
                  </CardContent>
                </Card>
              </div>
            </CarouselItem>
          ))
        }
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
</script>

<template>
  <Carousel :opts="{ align: 'start' }" class="mx-auto w-full max-w-xs">
    <CarouselContent>
      <template v-for="(_, index) in 5" :key="index">
        <CarouselItem>
          <div class="p-1">
            <Card>
              <CardContent class="flex aspect-square items-center justify-center p-6">
                <span class="text-4xl font-semibold">{{ index + 1 }}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      </template>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Installation

```bash
npx starwind@latest add carousel --framework astro
```
</DocsTabsContent>
```bash
npx starwind@latest add carousel --framework react
```
</DocsTabsContent>
```bash
npx starwind@latest add carousel --framework vue
```
</DocsTabsContent>
</DocsTabs>

## Usage

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
---

<Carousel opts={{ align: "start" }} class="mx-auto w-full max-w-xs">
  <CarouselContent>
    {
      Array.from({ length: 5 }).map((_, index) => (
        <CarouselItem>
          <div class="p-1">
            <Card>
              <CardContent class="flex aspect-square items-center justify-center p-6">
                <span class="text-4xl font-semibold">{index + 1}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      ))
    }
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>
```
  </div>
  <div slot="react">
```tsx
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";

export function Example() {
  return (
    <Carousel opts={{ align: "start" }} className="mx-auto w-full max-w-xs">
      <CarouselContent>
        {
          Array.from({ length: 5 }).map((_, index) => (
            <CarouselItem key={index}>
              <div className="p-1">
                <Card>
                  <CardContent className="flex aspect-square items-center justify-center p-6">
                    <span className="text-4xl font-semibold">{index + 1}</span>
                  </CardContent>
                </Card>
              </div>
            </CarouselItem>
          ))
        }
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
</script>

<template>
  <Carousel :opts="{ align: 'start' }" class="mx-auto w-full max-w-xs">
    <CarouselContent>
      <template v-for="(_, index) in 5" :key="index">
        <CarouselItem>
          <div class="p-1">
            <Card>
              <CardContent class="flex aspect-square items-center justify-center p-6">
                <span class="text-4xl font-semibold">{{ index + 1 }}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      </template>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Composition

Place each slide inside `CarouselContent`, then add the controls beside it:

```text
Carousel
├── CarouselContent
│   ├── CarouselItem
│   └── CarouselItem
├── CarouselPrevious
└── CarouselNext
```

## Behavior

Carousel uses [Embla Carousel](https://www.embla-carousel.com/) for touch gestures, orientation,
looping, and plugin support.

## Multiple Items

Show multiple items at once by using responsive basis classes on carousel items.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
---

<Carousel opts={{ align: "start" }} class="mx-auto w-full max-w-sm">
  <CarouselContent>
    {
      Array.from({ length: 5 }).map((_, index) => (
        <CarouselItem class="md:basis-1/2 lg:basis-1/3">
          <div class="p-1">
            <Card>
              <CardContent class="flex aspect-square items-center justify-center p-6">
                <span class="text-2xl font-semibold">{index + 1}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      ))
    }
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>
```
  </div>
  <div slot="react">
```tsx
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";

export function Example() {
  return (
    <>
      <Carousel opts={{ align: "start" }} className="mx-auto w-full max-w-sm">
        <CarouselContent>
          {
            Array.from({ length: 5 }).map((_, index) => (
              <CarouselItem className="md:basis-1/2 lg:basis-1/3">
                <div className="p-1">
                  <Card>
                    <CardContent className="flex aspect-square items-center justify-center p-6">
                      <span className="text-2xl font-semibold">{index + 1}</span>
                    </CardContent>
                  </Card>
                </div>
              </CarouselItem>
            ))
          }
        </CarouselContent>
        <CarouselPrevious />
        <CarouselNext />
      </Carousel>
    </>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
</script>

<template>
  <Carousel :opts="{ align: 'start' }" class="mx-auto w-full max-w-sm">
    <CarouselContent>
      <template v-for="(_, index) in 5" :key="index">
        <CarouselItem class="md:basis-1/2 lg:basis-1/3">
          <div class="p-1">
            <Card>
              <CardContent class="flex aspect-square items-center justify-center p-6">
                <span class="text-2xl font-semibold">{{ index + 1 }}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      </template>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Vertical Carousel

Carousels can be oriented vertically by setting the `orientation` prop.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
---

<Carousel opts={{ align: "start" }} orientation="vertical" class="my-10 w-full max-w-xs">
  <CarouselContent class="h-[200px] min-w-[140px]">
    {
      Array.from({ length: 5 }).map((_, index) => (
        <CarouselItem class="aspect-square pt-1 md:basis-3/4">
          <div class="h-full p-1">
            <Card class="h-full">
              <CardContent class="flex h-full items-center justify-center p-6">
                <span class="text-3xl font-semibold">{index + 1}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      ))
    }
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>
```
  </div>
  <div slot="react">
```tsx
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";

export function Example() {
  return (
    <>
      <Carousel opts={{ align: "start" }} orientation="vertical" className="my-10 w-full max-w-xs">
        <CarouselContent className="h-[200px] min-w-[140px]">
          {
            Array.from({ length: 5 }).map((_, index) => (
              <CarouselItem className="aspect-square pt-1 md:basis-3/4">
                <div className="h-full p-1">
                  <Card className="h-full">
                    <CardContent className="flex h-full items-center justify-center p-6">
                      <span className="text-3xl font-semibold">{index + 1}</span>
                    </CardContent>
                  </Card>
                </div>
              </CarouselItem>
            ))
          }
        </CarouselContent>
        <CarouselPrevious />
        <CarouselNext />
      </Carousel>
    </>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
</script>

<template>
  <Carousel :opts="{ align: 'start' }" orientation="vertical" class="my-10 w-full max-w-xs">
    <CarouselContent class="h-[200px] min-w-[140px]">
      <template v-for="(_, index) in 5" :key="index">
        <CarouselItem class="aspect-square pt-1 md:basis-3/4">
          <div class="h-full p-1">
            <Card class="h-full">
              <CardContent class="flex h-full items-center justify-center p-6">
                <span class="text-3xl font-semibold">{{ index + 1 }}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      </template>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Looping Carousel

Enable infinite looping with the `loop` option.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
---

<Carousel opts={{ align: "start", loop: true }} class="mx-auto w-full max-w-xs">
  <CarouselContent>
    <CarouselItem>
      <div class="p-1">
        <Card class="bg-gradient-to-br from-blue-500 to-purple-600 text-white">
          <CardContent class="flex aspect-square items-center justify-center p-6">
            <span class="text-4xl font-semibold">∞</span>
          </CardContent>
        </Card>
      </div>
    </CarouselItem>
    <CarouselItem>
      <div class="p-1">
        <Card class="bg-gradient-to-br from-green-500 to-blue-600 text-white">
          <CardContent class="flex aspect-square items-center justify-center p-6">
            <span class="text-4xl font-semibold">Loop</span>
          </CardContent>
        </Card>
      </div>
    </CarouselItem>
    <CarouselItem>
      <div class="p-1">
        <Card class="bg-gradient-to-br from-pink-500 to-red-600 text-white">
          <CardContent class="flex aspect-square items-center justify-center p-6">
            <span class="text-4xl font-semibold">∞</span>
          </CardContent>
        </Card>
      </div>
    </CarouselItem>
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>
```
  </div>
  <div slot="react">
```tsx
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";

export function Example() {
  return (
    <>
      <Carousel opts={{ align: "start", loop: true }} className="mx-auto w-full max-w-xs">
        <CarouselContent>
          <CarouselItem>
            <div className="p-1">
              <Card className="bg-gradient-to-br from-blue-500 to-purple-600 text-white">
                <CardContent className="flex aspect-square items-center justify-center p-6">
                  <span className="text-4xl font-semibold">∞</span>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
          <CarouselItem>
            <div className="p-1">
              <Card className="bg-gradient-to-br from-green-500 to-blue-600 text-white">
                <CardContent className="flex aspect-square items-center justify-center p-6">
                  <span className="text-4xl font-semibold">Loop</span>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
          <CarouselItem>
            <div className="p-1">
              <Card className="bg-gradient-to-br from-pink-500 to-red-600 text-white">
                <CardContent className="flex aspect-square items-center justify-center p-6">
                  <span className="text-4xl font-semibold">∞</span>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        </CarouselContent>
        <CarouselPrevious />
        <CarouselNext />
      </Carousel>
    </>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
</script>

<template>
  <Carousel :opts="{ align: 'start', loop: true }" class="mx-auto w-full max-w-xs">
    <CarouselContent>
      <CarouselItem>
        <div class="p-1">
          <Card class="bg-gradient-to-br from-blue-500 to-purple-600 text-white">
            <CardContent class="flex aspect-square items-center justify-center p-6">
              <span class="text-4xl font-semibold">∞</span>
            </CardContent>
          </Card>
        </div>
      </CarouselItem>
      <CarouselItem>
        <div class="p-1">
          <Card class="bg-gradient-to-br from-green-500 to-blue-600 text-white">
            <CardContent class="flex aspect-square items-center justify-center p-6">
              <span class="text-4xl font-semibold">Loop</span>
            </CardContent>
          </Card>
        </div>
      </CarouselItem>
      <CarouselItem>
        <div class="p-1">
          <Card class="bg-gradient-to-br from-pink-500 to-red-600 text-white">
            <CardContent class="flex aspect-square items-center justify-center p-6">
              <span class="text-4xl font-semibold">∞</span>
            </CardContent>
          </Card>
        </div>
      </CarouselItem>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Plugins

Extend carousel functionality with Embla Carousel plugins. First install the plugin package, then manually initialize the Runtime primitive with `createCarousel`.

> **Info:** You need to set `autoInit={false}` on the Carousel component, so that you can manually initialize it with your plugins and any additional options.

```bash
# Install the autoplay plugin
npm install embla-carousel-autoplay
```

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
---

<Carousel
  id="carousel-autoplay"
  autoInit={false}
  opts={{ align: "start" }}
  class="mx-auto w-full max-w-xs"
>
  <CarouselContent>
    {
      Array.from({ length: 5 }).map((_, index) => (
        <CarouselItem>
          <div class="p-1">
            <Card>
              <CardContent class="flex aspect-square items-center justify-center p-6">
                <span class="text-4xl font-semibold">{index + 1}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      ))
    }
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

<script>
  import Autoplay from "embla-carousel-autoplay";

  import { createCarousel } from "@starwind-ui/astro/carousel";

  function initAutoplayCarousel() {
    const carouselElement = document.getElementById("carousel-autoplay");
    if (!carouselElement) return;
    createCarousel(carouselElement, {
      opts: { align: "start" },
      plugins: [
        Autoplay({
          delay: 2000,
        }),
      ],
    });
  }

  initAutoplayCarousel();

  document.addEventListener("astro:after-swap", initAutoplayCarousel);
  document.addEventListener("starwind:init", initAutoplayCarousel);
</script>
```
  </div>
  <div slot="react">
```tsx
import Autoplay from "embla-carousel-autoplay";
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";

const autoplayPlugins = [Autoplay({ delay: 2000 })];

export function Example() {
  return (
    <Carousel opts={{ align: "start" }} plugins={autoplayPlugins} className="mx-auto w-full max-w-xs">
      <CarouselContent>
        {Array.from({ length: 5 }, (_, index) => (
          <CarouselItem key={index}>
            <div className="p-1">
              <Card>
                <CardContent className="flex aspect-square items-center justify-center p-6">
                  <span className="text-4xl font-semibold">{index + 1}</span>
                </CardContent>
              </Card>
            </div>
          </CarouselItem>
        ))}
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Card, CardContent } from "@/components/starwind/card";
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/starwind/carousel";
import Autoplay from "embla-carousel-autoplay";

const plugins = [Autoplay({ delay: 2000 })];
</script>

<template>
  <Carousel
    id="carousel-autoplay"
    :plugins="plugins"
    :opts="{ align: 'start' }"
    class="mx-auto w-full max-w-xs"
  >
    <CarouselContent>
      <template v-for="(_, index) in 5" :key="index">
        <CarouselItem>
          <div class="p-1">
            <Card>
              <CardContent class="flex aspect-square items-center justify-center p-6">
                <span class="text-4xl font-semibold">{{ index + 1 }}</span>
              </CardContent>
            </Card>
          </div>
        </CarouselItem>
      </template>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## API Reference
### Carousel
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `autoInit` | `boolean` | No | - | Primitive override | Controls whether Runtime behavior initializes automatically. |
| `opts` | `CarouselOptions["opts"]` | No | - | Primitive override | Provides options to the underlying carousel engine. |
- Inherits div attributes.

### CarouselContent
- Inherits div attributes.

### CarouselItem
- Inherits div attributes.

### CarouselPrevious
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `size` | `"sm" \| "md" \| "lg" \| "icon-sm" \| "icon" \| "icon-lg"` | No | `"icon"` | Styled variant | Selects the component's visual size. |
| `variant` | `"default" \| "primary" \| "secondary" \| "outline" \| "ghost" \| "info" \| "success" \| "warning" \| "error"` | No | `"outline"` | Styled variant | Selects the component's visual variant. |
- Inherits button attributes.

### CarouselNext
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `size` | `"sm" \| "md" \| "lg" \| "icon-sm" \| "icon" \| "icon-lg"` | No | `"icon"` | Styled variant | Selects the component's visual size. |
| `variant` | `"default" \| "primary" \| "secondary" \| "outline" \| "ghost" \| "info" \| "success" \| "warning" \| "error"` | No | `"outline"` | Styled variant | Selects the component's visual variant. |
- Inherits button attributes.
### Primitive And Runtime API
Behavior, state, events, form participation, and imperative methods are documented in the lower-level references.
- Primitive: [Carousel Primitive](/docs/primitives/carousel/)
- Runtime factory: [`createCarousel`](/docs/runtime/#create-carousel) from `@starwind-ui/runtime/carousel`

## Changelog

### v2.0.1

- Named the generated aggregate default export so React and Astro tooling can identify the installed component cleanly.

### v2.0.0

- Rebuilt Carousel on Starwind Runtime for navigation, orientation, looping, and plugin lifecycle.
- See the [Carousel Primitive](/docs/primitives/carousel/) for the underlying unstyled anatomy and behavior API.