Carousel
A slideshow component that cycles through elements.
Anatomy
To set up the carousel correctly, you'll need to understand its anatomy and how we name its parts.
Each part includes a
data-part
attribute to help identify them in the DOM.
Examples
Learn how to use the Carousel
component in your project. Let's take a look at
the most basic example:
import { Carousel } from '@ark-ui/react'
export const Basic = () => {
const images = [
'https://tinyurl.com/5b6ka8jd',
'https://tinyurl.com/7rmccdn5',
'https://tinyurl.com/59jxz9uu',
]
return (
<Carousel.Root>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{images.map((_, index) => (
<Carousel.Indicator key={index} index={index}>
{index + 1}
</Carousel.Indicator>
))}
</Carousel.IndicatorGroup>
<Carousel.Viewport>
<Carousel.ItemGroup>
{images.map((image, index) => (
<Carousel.Item key={index} index={index}>
<img src={image} alt={`Slide ${index}`} />
</Carousel.Item>
))}
</Carousel.ItemGroup>
</Carousel.Viewport>
</Carousel.Root>
)
}
import { Index } from 'solid-js'
import { Carousel } from '@ark-ui/solid'
export const Basic = () => {
const images = [
'https://tinyurl.com/5b6ka8jd',
'https://tinyurl.com/7rmccdn5',
'https://tinyurl.com/59jxz9uu',
'https://tinyurl.com/6jurv23t',
'https://tinyurl.com/yp4rfum7',
]
return (
<Carousel.Root>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Index each={images}>
{(_, index) => <Carousel.Indicator index={index}>{index + 1}</Carousel.Indicator>}
</Index>
</Carousel.IndicatorGroup>
<Carousel.Viewport>
<Carousel.ItemGroup>
<Index each={images}>
{(image, index) => (
<Carousel.Item index={index}>
<img src={image()} alt={`Slide ${index}`} />
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
</Carousel.Viewport>
</Carousel.Root>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue'
const images = [
'https://tinyurl.com/5b6ka8jd',
'https://tinyurl.com/7rmccdn5',
'https://tinyurl.com/59jxz9uu',
'https://tinyurl.com/6jurv23t',
'https://tinyurl.com/yp4rfum7',
]
</script>
<template>
<Carousel.Root>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in images" :key="idx" :index="idx">
{{ idx + 1 }}
</Carousel.Indicator>
</Carousel.IndicatorGroup>
<Carousel.Viewport>
<Carousel.ItemGroup>
<Carousel.Item v-for="(image, idx) in images" :key="idx" :index="idx">
<img
:src="image"
alt=""
:style="{ height: '300px', width: '100%', objectFit: 'cover' }"
/>
</Carousel.Item>
</Carousel.ItemGroup>
</Carousel.Viewport>
</Carousel.Root>
</template>
Controlled Carousel
To create a controlled Carousel component, you can manage the state of the
carousel using the index
prop and update it when the onIndexChange
event
handler is called:
import { useState } from 'react'
import { Carousel } from '@ark-ui/react'
export const Controlled = () => {
const [currentIndex, setCurrentIndex] = useState(0)
const images = [
'https://tinyurl.com/5b6ka8jd',
'https://tinyurl.com/7rmccdn5',
'https://tinyurl.com/59jxz9uu',
]
return (
<Carousel.Root index={currentIndex} onIndexChange={(details) => setCurrentIndex(details.index)}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{images.map((_, index) => (
<Carousel.Indicator key={index} index={index}>
{index + 1}
</Carousel.Indicator>
))}
</Carousel.IndicatorGroup>
<Carousel.Viewport>
<Carousel.ItemGroup>
{images.map((image, index) => (
<Carousel.Item key={index} index={index}>
<img src={image} alt={`Slide ${index}`} />
</Carousel.Item>
))}
</Carousel.ItemGroup>
</Carousel.Viewport>
</Carousel.Root>
)
}
import { Index, createSignal } from 'solid-js'
import { Carousel } from '@ark-ui/solid'
export const Controlled = () => {
const [currentIndex, setCurrentIndex] = createSignal(0)
const images = [
'https://tinyurl.com/5b6ka8jd',
'https://tinyurl.com/7rmccdn5',
'https://tinyurl.com/59jxz9uu',
'https://tinyurl.com/6jurv23t',
'https://tinyurl.com/yp4rfum7',
]
return (
<>
<Carousel.Root
index={currentIndex()}
onIndexChange={(details) => setCurrentIndex(details.index)}
>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.Viewport>
<Carousel.ItemGroup>
<Index each={images}>
{(image, index) => (
<Carousel.Item index={index}>
<img src={image()} alt={`Slide ${index}`} />
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
</Carousel.Viewport>
</Carousel.Root>
</>
)
}
<script setup lang="ts">
import { ref } from 'vue'
import { Carousel } from '@ark-ui/vue'
const images = [
'https://tinyurl.com/5b6ka8jd',
'https://tinyurl.com/7rmccdn5',
'https://tinyurl.com/59jxz9uu',
'https://tinyurl.com/6jurv23t',
'https://tinyurl.com/yp4rfum7',
]
const index = ref(0)
</script>
<template>
<Carousel.Root v-model:index="index">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in images" :key="idx" :index="idx">
{{ idx + 1 }}
</Carousel.Indicator>
</Carousel.IndicatorGroup>
<Carousel.Viewport>
<Carousel.ItemGroup>
<Carousel.Item v-for="(image, idx) in images" :key="idx" :index="idx">
<img
:src="image"
alt=""
:style="{ height: '300px', width: '100%', objectFit: 'cover' }"
/>
</Carousel.Item>
</Carousel.ItemGroup>
</Carousel.Viewport>
</Carousel.Root>
</template>
Customizing the Carousel
You can customize the Carousel component by setting various props. Here's an example of a customized Carousel:
import { Carousel } from '@ark-ui/react'
export const Customized = () => {
const images = [
'https://tinyurl.com/5b6ka8jd',
'https://tinyurl.com/7rmccdn5',
'https://tinyurl.com/59jxz9uu',
]
return (
<Carousel.Root
align="center"
loop={true}
slidesPerView={2}
spacing="16px"
orientation="horizontal"
>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{images.map((_, index) => (
<Carousel.Indicator key={index} index={index}>
{index + 1}
</Carousel.Indicator>
))}
</Carousel.IndicatorGroup>
<Carousel.Viewport>
<Carousel.ItemGroup>
{images.map((image, index) => (
<Carousel.Item key={index} index={index}>
<img src={image} alt={`Slide ${index}`} />
</Carousel.Item>
))}
</Carousel.ItemGroup>
</Carousel.Viewport>
</Carousel.Root>
)
}
import { Index } from 'solid-js'
import { Carousel } from '@ark-ui/solid'
export const Customized = () => {
const images = [
'https://tinyurl.com/5b6ka8jd',
'https://tinyurl.com/7rmccdn5',
'https://tinyurl.com/59jxz9uu',
]
return (
<Carousel.Root
align="center"
loop={true}
slidesPerView={2}
spacing="16px"
orientation="horizontal"
>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Index each={images}>
{(_, index) => <Carousel.Indicator index={index}>{index + 1}</Carousel.Indicator>}
</Index>
</Carousel.IndicatorGroup>
<Carousel.Viewport>
<Carousel.ItemGroup>
<Index each={images}>
{(image, index) => (
<Carousel.Item index={index}>
<img src={image()} alt={`Slide ${index}`} />
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
</Carousel.Viewport>
</Carousel.Root>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue'
const images = [
'https://tinyurl.com/5b6ka8jd',
'https://tinyurl.com/7rmccdn5',
'https://tinyurl.com/59jxz9uu',
'https://tinyurl.com/6jurv23t',
'https://tinyurl.com/yp4rfum7',
]
</script>
<template>
<Carousel.Root
:align="'center'"
loop
:slides-per-view="2"
spacing="16px"
orientation="horizontal"
>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in images" :key="idx" :index="idx">
{{ idx + 1 }}
</Carousel.Indicator>
</Carousel.IndicatorGroup>
<Carousel.Viewport>
<Carousel.ItemGroup>
<Carousel.Item v-for="(image, idx) in images" :key="idx" :index="idx">
<img
:src="image"
alt=""
:style="{ height: '300px', width: '100%', objectFit: 'cover' }"
/>
</Carousel.Item>
</Carousel.ItemGroup>
</Carousel.Viewport>
</Carousel.Root>
</template>
API Reference
Root
Prop | Default | Type |
---|---|---|
align | 'center' | 'end' | 'start' The alignment of the slides in the carousel. | |
asChild | boolean Render as a different element type. | |
defaultIndex | number The initial index of the carousel when it is first rendered. Use this when you do not need to control the state of the carousel. | |
id | string The unique identifier of the machine. | |
ids | Partial<{
root: string
viewport: string
slide(index: number): string
slideGroup: string
nextSlideTrigger: string
prevSlideTrigger: string
indicatorGroup: string
indicator(index: number): string
}> The ids of the elements in the carousel. Useful for composition. | |
index | number The current slide index. | |
loop | boolean Whether the carousel should loop around. | |
onIndexChange | (details: SlideChangeDetails) => void Function called when the slide changes. | |
orientation | 'horizontal' | 'horizontal' | 'vertical' The orientation of the carousel. |
slidesPerView | number | 'auto' The number of slides to show at a time. | |
spacing | string The amount of space between slides. |
Control
Prop | Default | Type |
---|---|---|
asChild | boolean Render as a different element type. |
IndicatorGroup
Prop | Default | Type |
---|---|---|
asChild | boolean Render as a different element type. |
Indicator
Prop | Default | Type |
---|---|---|
index | number | |
asChild | boolean Render as a different element type. | |
readOnly | boolean |
ItemGroup
Prop | Default | Type |
---|---|---|
asChild | boolean Render as a different element type. |
Item
Prop | Default | Type |
---|---|---|
index | number The index of the item. | |
asChild | boolean Render as a different element type. |
NextTrigger
Prop | Default | Type |
---|---|---|
asChild | boolean Render as a different element type. |
PrevTrigger
Prop | Default | Type |
---|---|---|
asChild | boolean Render as a different element type. |
Viewport
Prop | Default | Type |
---|---|---|
asChild | boolean Render as a different element type. |