Back to components
Components

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
modelValue0number
items[]unknown[]
slidesPerView1number
gap'1rem'string
hasArrowstrueboolean
hasDotstrueboolean
isLoopfalseboolean
autoplayfalseboolean
autoplayInterval4000number
transitionCarouselTransition.SLIDECarouselTransition
easingEasing.SMOOTHEasing
speed500number
pauseOnHovertrueboolean
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>
 
  • Type: number
  • Default: 0

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>
 
  • Type: unknown[]
  • Default: []

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>
 
  • Type: number
  • Default: 1

gap

Sets the space between slides. Accepts any CSS length.

 <template>
    <Carousel :items="slides" gap="2rem" />
</template>
 
  • Type: string
  • Default: '1rem'

hasArrows

Shows or hides the previous and next buttons.

 <template>
    <Carousel :items="slides" :hasArrows="false" />
</template>
 
  • Type: boolean
  • Default: true

hasDots

Shows or hides the page indicators.

 <template>
    <Carousel :items="slides" :hasDots="false" />
</template>
 
  • Type: boolean
  • Default: true

isLoop

Wraps around from the last page to the first one and vice versa.

 <template>
    <Carousel :items="slides" :isLoop="true" />
</template>
 
  • Type: boolean
  • Default: false

autoplay

Advances automatically every autoplayInterval milliseconds. Without isLoop, autoplay stops at the last page.

 <template>
    <Carousel :items="slides" :autoplay="true" :isLoop="true" />
</template>
 
  • Type: boolean
  • Default: false

autoplayInterval

Sets the time in milliseconds between automatic slide changes.

 <template>
    <Carousel :items="slides" :autoplay="true" :autoplayInterval="6000" />
</template>
 
  • Type: number
  • Default: 4000

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>
 
  • Type: CarouselTransition
  • Default: CarouselTransition.SLIDE

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>
 
  • Type: Easing
  • Default: Easing.SMOOTH

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>
 
  • Type: number
  • Default: 500

pauseOnHover

Pauses autoplay while the pointer is over the carousel or it has focus.

 <template>
    <Carousel :items="slides" :autoplay="true" :pauseOnHover="false" />
</template>
 
  • Type: boolean
  • Default: true

previousAriaLabel

Sets the aria-label of the previous button. Falls back to useDSConfig().slides.previousText().

 <template>
    <Carousel :items="slides" previousAriaLabel="Diapositiva anterior" />
</template>
 
  • Type: string

nextAriaLabel

Sets the aria-label of the next button. Falls back to useDSConfig().slides.nextText().

 <template>
    <Carousel :items="slides" nextAriaLabel="Diapositiva siguiente" />
</template>
 
  • Type: string

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>
 
  • Type: string

ariaLabel

Sets the accessible name of the carousel region.

 <template>
    <Carousel :items="slides" ariaLabel="Featured content" />
</template>
 
  • Type: string

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>