Carousel

Un carrousel avec mouvement et balayage construit avec Embla.

Utilisation

Utilisez le composant Carrousel pour afficher une liste d'éléments dans un carrousel.

<script setup lang="ts">
const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]
</script>

<template>
  <UCarousel
    v-slot="{ item }"
    loop
    arrows
    :autoplay="{ delay: 2000 }"
    wheel-gestures
    :prev="{ variant: 'solid' }"
    :next="{ variant: 'solid' }"
    :items="items"
    :ui="{
      item: 'basis-1/3 ps-0',
      prev: 'sm:start-8',
      next: 'sm:end-8',
      container: 'ms-0'
    }"
  >
    <img :src="item" width="320" height="320">
  </UCarousel>
</template>
Utilisez votre souris pour faire glisser le carrousel horizontalement sur le bureau.

Éléments

Utilisez le prop items comme un tableau et rendre chaque élément en utilisant l'emplacement par défaut:

<script setup lang="ts">
const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]
</script>

<template>
  <UCarousel v-slot="{ item }" :items="items" class="w-full max-w-xs mx-auto">
    <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>

Vous pouvez également passer un tableau d'objets avec les propriétés suivantes:

  • xclass?: anyxx{lang="ts-type"}
  • xui?: { item?: ClassNameValue }xx{lang="ts-type"}

Vous pouvez contrôler le nombre d'éléments visibles en utilisant les classes d'utilitaires basis/width sur le item:

<script setup lang="ts">
const items = [
  'https://picsum.photos/468/468?random=1',
  'https://picsum.photos/468/468?random=2',
  'https://picsum.photos/468/468?random=3',
  'https://picsum.photos/468/468?random=4',
  'https://picsum.photos/468/468?random=5',
  'https://picsum.photos/468/468?random=6'
]
</script>

<template>
  <UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-1/3' }">
    <img :src="item" width="234" height="234" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>

Définition

Utilisez la prop orientation pour modifier l'orientation de Progress. Defaults à horizontal.

Utilisez votre souris pour faire glisser le carrousel verticalement sur le bureau.
<script setup lang="ts">
const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]
</script>

<template>
  <UCarousel
    v-slot="{ item }"
    orientation="vertical"
    :items="items"
    :ui="{ container: 'h-[336px]' }"
    class="w-full max-w-xs mx-auto"
  >
    <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>
Vous devez spécifier un height sur le conteneur en orientation verticale.

flèches

Utilisez le prop arrows pour afficher les boutons précédent et suivant.

<script setup lang="ts">
const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]
</script>

<template>
  <UCarousel v-slot="{ item }" arrows :items="items" class="w-full max-w-xs mx-auto">
    <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>

Prev/Suivant

Utilisez les accessoires prev et next pour personnaliser les boutons précédent et suivant avec n'importe quel accessoire Button.

<script setup lang="ts">
const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]
</script>

<template>
  <UCarousel
    v-slot="{ item }"
    arrows
    :prev="{ color: 'primary' }"
    :next="{ variant: 'solid' }"
    :items="items"
    class="w-full max-w-xs mx-auto"
  >
    <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>

Prev/Icônes suivantes

Utilisez les accessoires prev-icon et next-icon pour personnaliser les boutons Icon.

<script setup lang="ts">
defineProps<{
  prevIcon?: string
  nextIcon?: string
}>()

const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]
</script>

<template>
  <UCarousel
    v-slot="{ item }"
    arrows
    :prev-icon="prevIcon"
    :next-icon="nextIcon"
    :items="items"
    class="w-full max-w-xs mx-auto"
  >
    <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>
Vous pouvez personnaliser ces icônes globalement dans votre app.config.ts sous la touche ui.icons.arrowLeft/ui.icons.arrowRight.
Vous pouvez personnaliser ces icônes globalement dans votre vite.config.ts sous la touche ui.icons.arrowLeft/ui.icons.arrowRight.

Dots

Utilisez le prop dots pour afficher une liste de points à faire défiler vers une diapositive spécifique.

<script setup lang="ts">
const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]
</script>

<template>
  <UCarousel v-slot="{ item }" dots :items="items" class="w-full max-w-xs mx-auto">
    <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>

Le nombre de points est basé sur le nombre de diapositives affichées dans la vue:

<script setup lang="ts">
const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]
</script>

<template>
  <UCarousel v-slot="{ item }" dots :items="items" :ui="{ item: 'basis-1/3' }">
    <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>

Plugins

Le composant Carousel implémente le plugin officiel Embla Carousel .

Autoplay électronique

Ce plugin est utilisé pour étendre Embla Carousel avec la fonctionnalité autoplay.

Utilisez la prop autoplay en tant que booléen ou objet pour configurer le plugin Autoplay .

<script setup lang="ts">
const items = [
  'https://picsum.photos/468/468?random=1',
  'https://picsum.photos/468/468?random=2',
  'https://picsum.photos/468/468?random=3',
  'https://picsum.photos/468/468?random=4',
  'https://picsum.photos/468/468?random=5',
  'https://picsum.photos/468/468?random=6'
]
</script>

<template>
  <UCarousel
    v-slot="{ item }"
    loop
    arrows
    dots
    :autoplay="{ delay: 2000 }"
    :items="items"
    :ui="{ item: 'basis-1/3' }"
  >
    <img :src="item" width="234" height="234" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>
Dans cet exemple, nous utilisons la prop loop pour un carrousel infini.

Auto Scroll électronique

Ce plugin est utilisé pour étendre Embla Carousel avec la fonctionnalité auto scroll.

Utilisez la prop auto-scroll en tant que booléen ou objet pour configurer le plugin Auto Scroll .

<script setup lang="ts">
const items = [
  'https://picsum.photos/468/468?random=1',
  'https://picsum.photos/468/468?random=2',
  'https://picsum.photos/468/468?random=3',
  'https://picsum.photos/468/468?random=4',
  'https://picsum.photos/468/468?random=5',
  'https://picsum.photos/468/468?random=6'
]
</script>

<template>
  <UCarousel
    v-slot="{ item }"
    loop
    dots
    arrows
    auto-scroll
    :items="items"
    :ui="{ item: 'basis-1/3' }"
  >
    <img :src="item" width="234" height="234" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>
Dans cet exemple, nous utilisons la prop loop pour un carrousel infini.

Auto Hauteur

Ce plugin est utilisé pour étendre Embla Carousel avec la fonctionnalité auto height. Il modifie la hauteur du conteneur de carrousel pour s'adapter à la hauteur de la diapositive la plus haute en vue.

Utilisez la prop auto-height en tant que booléen ou objet pour configurer le plugin Auto Height .

<script setup lang="ts">
const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/320?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/320?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/320?random=6'
]
</script>

<template>
  <UCarousel
    v-slot="{ item }"
    auto-height
    arrows
    dots
    :items="items"
    :ui="{
      container: 'transition-[height]',
      controls: 'absolute -top-8 inset-x-12',
      dots: '-top-7',
      dot: 'w-6 h-1'
    }"
    class="w-full max-w-xs mx-auto"
  >
    <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>
En este ejemplo, agregamos la clase transition-[height] en el contenedor para animar el cambio de altura.

Clase

Class Names est un plugin utilitaire class name toggle pour Embla Carousel qui vous permet d'automatiser la bascule des noms de classe sur votre carrousel.

Utilisez la prop class-names en tant que booléen ou objet pour configurer le plugin noms de classe ](https://www.embla-carousel.com/docs/v8/plugins/class-names).

<script setup lang="ts">
const items = [
  'https://picsum.photos/528/528?random=1',
  'https://picsum.photos/528/528?random=2',
  'https://picsum.photos/528/528?random=3',
  'https://picsum.photos/528/528?random=4',
  'https://picsum.photos/528/528?random=5',
  'https://picsum.photos/528/528?random=6'
]
</script>

<template>
  <UCarousel
    v-slot="{ item }"
    class-names
    arrows
    :items="items"
    :ui="{
      item: 'basis-[70%] transition-opacity [&:not(.is-snapped)]:opacity-10'
    }"
    class="mx-auto max-w-sm"
  >
    <img :src="item" width="264" height="264" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>
Dans cet exemple, nous ajoutons les classes transition-opacity [&:not(.is-snapped)]:opacity-10 sur le item pour animer le changement d'opacité.

Fade

Ce plugin est utilisé pour remplacer la fonctionnalité de défilement Embla Carousel par fade transitions.

Utilisez la prop fade en tant que booléen ou objet pour configurer le plugin Fade .

<script setup lang="ts">
const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]
</script>

<template>
  <UCarousel
    v-slot="{ item }"
    fade
    arrows
    dots
    :items="items"
    class="w-full max-w-xs mx-auto"
  >
    <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>

Wheel Gestes

Ce plugin est utilisé pour étendre Embla Carousel avec la possibilité d'utiliser la souris/trackpad wheel** pour naviguer dans le carrousel.

Utilisez la prop wheel-gestures en tant que booléen ou objet pour configurer le plugin Wheel Gestures .

Utilisez la molette de votre souris pour faire défiler le carrousel.
<script setup lang="ts">
const items = [
  'https://picsum.photos/468/468?random=1',
  'https://picsum.photos/468/468?random=2',
  'https://picsum.photos/468/468?random=3',
  'https://picsum.photos/468/468?random=4',
  'https://picsum.photos/468/468?random=5',
  'https://picsum.photos/468/468?random=6'
]
</script>

<template>
  <UCarousel
    v-slot="{ item }"
    loop
    wheel-gestures
    :items="items"
    :ui="{ item: 'basis-1/3' }"
  >
    <img :src="item" width="234" height="234" class="rounded-lg" loading="lazy">
  </UCarousel>
</template>

Exemples

Avec vignettes

Vous pouvez utiliser la méthode scrollTo sur [emblaApixph186#expose) pour afficher les vignettes sous le carrousel qui naviguent vers une diapositive spécifique.

<script setup lang="ts">
const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]

const carousel = useTemplateRef('carousel')
const activeIndex = ref(0)

function onClickPrev() {
  activeIndex.value--
}
function onClickNext() {
  activeIndex.value++
}
function onSelect(index: number) {
  activeIndex.value = index
}

function select(index: number) {
  activeIndex.value = index

  carousel.value?.emblaApi?.scrollTo(index)
}
</script>

<template>
  <div class="flex-1 w-full">
    <UCarousel
      ref="carousel"
      v-slot="{ item }"
      arrows
      :items="items"
      :prev="{ onClick: onClickPrev }"
      :next="{ onClick: onClickNext }"
      class="w-full max-w-xs mx-auto"
      @select="onSelect"
    >
      <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
    </UCarousel>

    <div class="flex gap-1 justify-between pt-4 max-w-xs mx-auto">
      <div
        v-for="(item, index) in items"
        :key="index"
        class="size-11 opacity-25 hover:opacity-100 transition-opacity"
        :class="{ 'opacity-100': activeIndex === index }"
        @click="select(index)"
      >
        <img :src="item" width="44" height="44" class="rounded-lg" loading="lazy">
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, useTemplateRef } from 'vue'

const items = [
  'https://picsum.photos/640/640?random=1',
  'https://picsum.photos/640/640?random=2',
  'https://picsum.photos/640/640?random=3',
  'https://picsum.photos/640/640?random=4',
  'https://picsum.photos/640/640?random=5',
  'https://picsum.photos/640/640?random=6'
]

const carousel = useTemplateRef('carousel')
const activeIndex = ref(0)

function onClickPrev() {
  activeIndex.value--
}
function onClickNext() {
  activeIndex.value++
}
function onSelect(index: number) {
  activeIndex.value = index
}

function select(index: number) {
  activeIndex.value = index

  carousel.value?.emblaApi?.scrollTo(index)
}
</script>

<template>
  <div class="flex-1 w-full">
    <UCarousel
      ref="carousel"
      v-slot="{ item }"
      arrows
      :items="items"
      :prev="{ onClick: onClickPrev }"
      :next="{ onClick: onClickNext }"
      class="w-full max-w-xs mx-auto"
      @select="onSelect"
    >
      <img :src="item" width="320" height="320" class="rounded-lg" loading="lazy">
    </UCarousel>

    <div class="flex gap-1 justify-between pt-4 max-w-xs mx-auto">
      <div
        v-for="(item, index) in items"
        :key="index"
        class="size-11 opacity-25 hover:opacity-100 transition-opacity"
        :class="{ 'opacity-100': activeIndex === index }"
        @click="select(index)"
      >
        <img :src="item" width="44" height="44" class="rounded-lg" loading="lazy">
      </div>
    </div>
  </div>
</template>

API

Props équipements

Prop Default Type
as
'div'
any

The element or component this component should render as.

prev
{ size: 'md', color: 'neutral', variant: 'link' }
Omit<ButtonProps, LinkPropsKeys>

Configure the prev button when arrows are enabled.

prevIcon
appConfig.ui.icons.arrowLeft
any

The icon displayed in the prev button.

next
{ size: 'md', color: 'neutral', variant: 'link' }
Omit<ButtonProps, LinkPropsKeys>

Configure the next button when arrows are enabled.

nextIcon
appConfig.ui.icons.arrowRight
any

The icon displayed in the next button.

arrows
false
boolean

Display prev and next buttons to scroll the carousel.

dots
false
boolean

Display dots to scroll to a specific slide.

orientation
'horizontal'
"vertical" | "horizontal"

The orientation of the carousel.

items
T[]
autoplay
false
boolean | Partial<CreateOptionsType<OptionsType>>

Enable Autoplay plugin

autoScroll
false
boolean | Partial<CreateOptionsType<OptionsType>>

Enable Auto Scroll plugin

autoHeight
false
boolean | Partial<CreateOptionsType<{ active: boolean; breakpoints: { [key: string]: Omit<Partial<any>, "breakpoints">; }; }>>

Enable Auto Height plugin

classNames
false
boolean | Partial<CreateOptionsType<OptionsType>>

Enable Class Names plugin

fade
false
boolean | Partial<CreateOptionsType<{ active: boolean; breakpoints: { [key: string]: Omit<Partial<any>, "breakpoints">; }; }>>

Enable Fade plugin

wheelGestures
false
boolean | WheelGesturesPluginOptions

Enable Wheel Gestures plugin

align
'center'
"start" | "center" | "end" | (viewSize: number, snapSize: number, index: number): number
containScroll
'trimSnaps'
false | "trimSnaps" | "keepSnaps"
slidesToScroll
1
number | "auto"
dragFree
false
boolean
dragThreshold
10
number
inViewThreshold
0
number | number[]
loop
false
boolean
skipSnaps
false
boolean
duration
25
number
startIndex
0
number
watchDrag
true
false | true | (emblaApi: EmblaCarouselType, evt: PointerEventType): boolean | void
watchResize
true
false | true | (emblaApi: EmblaCarouselType, entries: ResizeObserverEntry[]): boolean | void
watchSlides
true
false | true | (emblaApi: EmblaCarouselType, mutations: MutationRecord[]): boolean | void
watchFocus
true
false | true | (emblaApi: EmblaCarouselType, evt: FocusEvent): boolean | void
active
true
boolean
breakpoints
{}
{ [key: string]: Omit<Partial<CreateOptionsType<{ align: AlignmentOptionType; axis: AxisOptionType; container: string | HTMLElement | null; slides: string | HTMLElement[] | NodeListOf<HTMLElement> | null; containScroll: ScrollContainOptionType; direction: AxisDirectionOptionType; slidesToScroll: SlidesToScrollOptionType; dragFree: boolean; dragThreshold: number; inViewThreshold: number | number[] | undefined; loop: boolean; skipSnaps: boolean; duration: number; startIndex: number; watchDrag: DragHandlerOptionType; watchResize: ResizeHandlerOptionType; watchSlides: SlidesHandlerOptionType; watchFocus: FocusHandlerOptionType; }>>, "breakpoints">; }
ui
{ root?: SlotClass; viewport?: SlotClass; container?: SlotClass; item?: SlotClass; controls?: SlotClass; arrows?: SlotClass; prev?: SlotClass; next?: SlotClass; dots?: SlotClass; dot?: SlotClass; }

Slots

Slot Type
default
{ item: T; index: number; }

Emis

Event Type
select
[selectedIndex: number]

Expose à

Vous pouvez accéder à l'instance du composant typé à l'aide de useTemplateRef.

<script setup lang="ts">
const carousel = useTemplateRef('carousel')
</script>

<template>
  <UCarousel ref="carousel" />
</template>

Cela vous donnera accès à ce qui suit:

nomtype
emblaRefx{lang="ts-type"}Ref<HTMLElement | null>
emblaApixRef<EmblaCarouselType | null>x{lang="ts-type"}x

Thème

app.config.ts
export default defineAppConfig({
  ui: {
    carousel: {
      slots: {
        root: 'relative focus:outline-none',
        viewport: 'overflow-hidden',
        container: 'flex items-start',
        item: 'min-w-0 shrink-0 basis-full',
        controls: '',
        arrows: '',
        prev: 'absolute rounded-full',
        next: 'absolute rounded-full',
        dots: 'absolute inset-x-0 -bottom-7 flex flex-wrap items-center justify-center gap-3',
        dot: [
          'cursor-pointer size-3 bg-accented rounded-full outline-inverted/25 focus-visible:outline-3',
          'transition'
        ]
      },
      variants: {
        orientation: {
          vertical: {
            container: 'flex-col -mt-4',
            item: 'pt-4',
            prev: 'top-4 sm:-top-12 left-1/2 -translate-x-1/2 rotate-90 rtl:-rotate-90',
            next: 'bottom-4 sm:-bottom-12 left-1/2 -translate-x-1/2 rotate-90 rtl:-rotate-90'
          },
          horizontal: {
            container: 'flex-row -ms-4',
            item: 'ps-4',
            prev: 'start-4 sm:-start-12 top-1/2 -translate-y-1/2',
            next: 'end-4 sm:-end-12 top-1/2 -translate-y-1/2'
          }
        },
        active: {
          true: {
            dot: 'data-[state=active]:bg-inverted'
          }
        }
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        carousel: {
          slots: {
            root: 'relative focus:outline-none',
            viewport: 'overflow-hidden',
            container: 'flex items-start',
            item: 'min-w-0 shrink-0 basis-full',
            controls: '',
            arrows: '',
            prev: 'absolute rounded-full',
            next: 'absolute rounded-full',
            dots: 'absolute inset-x-0 -bottom-7 flex flex-wrap items-center justify-center gap-3',
            dot: [
              'cursor-pointer size-3 bg-accented rounded-full outline-inverted/25 focus-visible:outline-3',
              'transition'
            ]
          },
          variants: {
            orientation: {
              vertical: {
                container: 'flex-col -mt-4',
                item: 'pt-4',
                prev: 'top-4 sm:-top-12 left-1/2 -translate-x-1/2 rotate-90 rtl:-rotate-90',
                next: 'bottom-4 sm:-bottom-12 left-1/2 -translate-x-1/2 rotate-90 rtl:-rotate-90'
              },
              horizontal: {
                container: 'flex-row -ms-4',
                item: 'ps-4',
                prev: 'start-4 sm:-start-12 top-1/2 -translate-y-1/2',
                next: 'end-4 sm:-end-12 top-1/2 -translate-y-1/2'
              }
            },
            active: {
              true: {
                dot: 'data-[state=active]:bg-inverted'
              }
            }
          }
        }
      }
    })
  ]
})

Changelog

No recent changes