Carousel
Displays a set of slides one or several at a time, with arrows, dots, swipe, keyboard navigation and optional autoplay.
Component
- Slide 1
Props
| Props | Default | Type |
|---|---|---|
modelValue | 0 | number |
items | [] | unknown[] |
slidesPerView | 1 | number |
gap | '1rem' | string |
hasArrows | true | boolean |
hasDots | true | boolean |
isLoop | false | boolean |
autoplay | false | boolean |
autoplayInterval | 4000 | number |
transition | CarouselTransition.SLIDE | CarouselTransition |
easing | Easing.SMOOTH | Easing |
speed | 500 | number |
pauseOnHover | true | boolean |
previousAriaLabel | — | string |
nextAriaLabel | — | string |
dotAriaLabel | — | string |
ariaLabel | — | string |
Slots
| Name | Description |
|---|---|
default | Renders each slide. Receives `item` (the entry of `items`) and `index`. |
<template>
<Carousel :items="slides">
<template #default="{ item, index }">
<ContentPlaceholder :text="`${index + 1}. ${item.title}`" />
</template>
</Carousel>
</template>
<script setup lang="ts">
const slides = [{ title: 'First' }, { title: 'Second' }, { title: 'Third' }]
</script>
Usage
modelValue
Sets the active page. You can bind it with v-model to control the carousel from outside.
<template>
<Carousel v-model="page" :items="slides" />
</template>
<script setup lang="ts">
const page = ref(0)
</script>
items
Defines the slides to render. Each entry is passed to the default slot.
<template>
<Carousel :items="slides" />
</template>
<script setup lang="ts">
const slides = ['Slide 1', 'Slide 2', 'Slide 3']
</script>
slidesPerView
Sets how many slides are visible at once. The number of pages is items.length - slidesPerView + 1.
<template>
<Carousel :items="slides" :slidesPerView="3" />
</template>
gap
Sets the space between slides. Accepts any CSS length.
<template>
<Carousel :items="slides" gap="2rem" />
</template>
hasArrows
Shows or hides the previous and next buttons.
<template>
<Carousel :items="slides" :hasArrows="false" />
</template>
hasDots
Shows or hides the page indicators.
<template>
<Carousel :items="slides" :hasDots="false" />
</template>
isLoop
Wraps around from the last page to the first one and vice versa.
<template>
<Carousel :items="slides" :isLoop="true" />
</template>
autoplay
Advances automatically every autoplayInterval milliseconds. Without isLoop, autoplay stops at the last page.
<template>
<Carousel :items="slides" :autoplay="true" :isLoop="true" />
</template>
autoplayInterval
Sets the time in milliseconds between automatic slide changes.
<template>
<Carousel :items="slides" :autoplay="true" :autoplayInterval="6000" />
</template>
transition
Sets the animation between slides via the CarouselTransition enum. FADE and ZOOM show one slide at a time, so slidesPerView is ignored.
<template>
<Carousel :items="slides" :transition="CarouselTransition.FADE" />
</template>
Options
| Value | Description |
|---|---|
SLIDE | slide |
FADE | fade |
ZOOM | zoom |
NONE | none |
easing
Sets the timing curve of the transition via the shared Easing enum, which the Lightbox also uses.
<template>
<Carousel :items="slides" :easing="Easing.BOUNCE" />
</template>
Options
| Value | Description |
|---|---|
SMOOTH | Fast start with a long, gentle finish |
EASE | CSS `ease` |
EASE_IN | CSS `ease-in` |
EASE_OUT | CSS `ease-out` |
EASE_IN_OUT | CSS `ease-in-out` |
LINEAR | Constant speed |
BOUNCE | Slightly overshoots the target before settling |
speed
Sets the duration in milliseconds of the slide transition.
<template>
<Carousel :items="slides" :speed="800" />
</template>
pauseOnHover
Pauses autoplay while the pointer is over the carousel or it has focus.
<template>
<Carousel :items="slides" :autoplay="true" :pauseOnHover="false" />
</template>
previousAriaLabel
Sets the aria-label of the previous button. Falls back to useDSConfig().slides.previousText().
<template>
<Carousel :items="slides" previousAriaLabel="Diapositiva anterior" />
</template>
nextAriaLabel
Sets the aria-label of the next button. Falls back to useDSConfig().slides.nextText().
<template>
<Carousel :items="slides" nextAriaLabel="Diapositiva siguiente" />
</template>
dotAriaLabel
Sets the prefix of each indicator's aria-label. The page number is appended. Falls back to useDSConfig().slides.goToSlideText().
<template>
<Carousel :items="slides" dotAriaLabel="Ir a la diapositiva" />
</template>
ariaLabel
Sets the accessible name of the carousel region.
<template>
<Carousel :items="slides" ariaLabel="Featured content" />
</template>
Accessibility
The carousel is a <section> with aria-roledescription="carousel", and each slide is a list item with aria-roledescription="slide". Slides outside the viewport are hidden from assistive technology. Always set ariaLabel so the region has a name. The carousel itself is not a tab stop: keyboard users reach it through the arrow buttons and dots, and the arrow keys work while focus is inside it.
| Value | Description |
|---|---|
ArrowRight | Goes to the next page. |
ArrowLeft | Goes to the previous page. |
Swiping on touch screens and dragging with a pointer also change the page. Transitions are disabled when the user prefers reduced motion.
Emits
| Value | Description |
|---|---|
@update:modelValue | Emitted with the new page index when the active page changes. |
@change | Emitted with the new page index when the active page changes. |
Example
<template>
<Carousel :items="slides" @change="handleChange" />
</template>
<script setup lang="ts">
const handleChange = (page: number) => {
console.log('Page', page)
}
</script>
Methods
| Value | Description |
|---|---|
next() | Goes to the next page, wrapping around when `isLoop` is enabled. |
prev() | Goes to the previous page, wrapping around when `isLoop` is enabled. |
goTo(index) | Goes to the given page index, clamped to the valid range. |
<template>
<Carousel ref="carousel" :items="slides" />
<ActionButton text="Next" @click="carousel?.next()" />
</template>
<script setup lang="ts">
const carousel = ref()
</script>