vue-carousel-3d

Beautiful, flexible and touch supported 3D Carousel for Vue.js
103,358 979
Install
npm install vue-carousel-3d
Latest Version:2.1.1
Vue:3
Older releases:2
License:MIT
Last Updated:Oct 21, 2026
Links: GitHub  ·  npm
Maintainer: wlada

Vue Carousel 3D

CI npm version npm downloads license

A compact, flexible and touch-friendly 3D carousel for Vue 3.

2.x supports Vue ^3.5.0. Existing Vue 2 users should remain on vue-carousel-3d@1.

Features

  • Real 3D composition: perspective, spacing, inverse scaling and directional bias.
  • Pointer, touch, mouse and keyboard navigation with native, accessible buttons.
  • Optional navigation dots (dots) with aria-current state.
  • Custom control content through prev / next slots.
  • beforeSlideChange guard to block navigation, and one-directional / loop modes.
  • Autoplay with hover pause, and lazy slide content for image-heavy carousels.
  • SSR-safe module, TypeScript declarations and ESM / CommonJS / UMD outputs.

Installation

pnpm add vue-carousel-3d
npm install vue-carousel-3d

Quick start

<template>
  <carousel-3d dots controls-visible aria-label="Featured projects">
    <slide v-for="(project, index) in projects" :key="project.id" :index="index">
      <img :src="https://raw.githubusercontent.com/wlada/vue-carousel-3d/HEAD/project.image" :alt="project.title">
    </slide>
  </carousel-3d>
</template>

<script setup>
import { Carousel3d, Slide } from 'vue-carousel-3d'

const projects = [
  { id: 1, title: 'Orbit', image: '/images/orbit.jpg' },
  { id: 2, title: 'Depth', image: '/images/depth.jpg' }
]
</script>

Each slide needs a stable, zero-based index. For dynamic collections, also pass :count="projects.length" so the carousel recomputes its layout immediately.

Local registration

<template>
  <carousel-3d controls-visible aria-label="Featured projects">
    <slide v-for="(project, index) in projects" :key="project.id" :index="index">
      {{ project.title }}
    </slide>
  </carousel-3d>
</template>

<script>
import { Carousel3d, Slide } from 'vue-carousel-3d'

export default {
  components: { Carousel3d, Slide },
  data: () => ({ projects: [] })
}
</script>

Each slide needs a stable, zero-based index. For dynamic collections, also pass :count="projects.length" to the carousel.

Global registration

import { createApp } from 'vue'
import Carousel3d from 'vue-carousel-3d'

createApp(App).use(Carousel3d)

This registers <carousel-3d> and <slide> globally.

Common patterns

Navigation dots and custom controls

<carousel-3d dots controls-visible>
  <template #prev>
    <span aria-hidden="true">&larr;</span>
  </template>
  <template #next>
    <span aria-hidden="true">&rarr;</span>
  </template>
  <slide v-for="(item, index) in items" :key="item.id" :index="index">
    {{ item.title }}
  </slide>
</carousel-3d>

Blocking navigation

<carousel-3d :before-slide-change="(index) => index !== 3">
  <!-- slides -->
</carousel-3d>

Returning false cancels the move for arrows, swipes, dots and programmatic navigation. @before-slide-change still fires for allowed moves.

Lazy slide content

<carousel-3d lazy :display="3" :count="items.length">
  <slide v-for="(item, index) in items" :key="item.id" :index="index">
    <img :src="https://raw.githubusercontent.com/wlada/vue-carousel-3d/HEAD/item.image" :alt="item.title">
  </slide>
</carousel-3d>

Programmatic navigation

<carousel-3d ref="carousel">
  <!-- slides -->
</carousel-3d>

<button type="button" @click="$refs.carousel.goSlide(3)">
  Open slide 4
</button>

API overview

Prop Purpose
display / width / height / space Visible slide count and geometry.
perspective / inverseScaling / bias 3D depth and composition.
controlsVisible / controlsPrevHtml / controlsNextHtml Built-in controls.
dots / dotsPosition Navigation dots (bottom / top).
autoplay / autoplayTimeout / autoplayHoverPause Automatic rotation.
loop / oneDirectional / startIndex Navigation behavior.
clickable / disable3d / minSwipeDistance Interaction and flat mode.
lazy Render slide content only near the current slide.
beforeSlideChange Return false to cancel a navigation.

Events: before-slide-change, after-slide-change, last-slide. Methods: goNext(), goPrev(), goSlide(index), goFar(index). See the full API reference for details.

When to use it

This component is a good fit when you want a distinctive 3D stack and need touch handling, keyboard support and SSR safety without building the math yourself.

Carousels can hurt readability, so use autoplay sparingly and always provide a way to pause or navigate manually. Consider a plain grid or a flat carousel (disable-3d) when motion is a concern.

Browser support

Modern evergreen browsers (current Chrome, Firefox, Safari and Edge). IE11 and older engines are not supported.

Development

pnpm install
pnpm dev

Useful checks:

pnpm lint
pnpm test
pnpm build
pnpm docs:build
pnpm pack:check

Node 20.19+ or 22.13+ and pnpm 10.34.5 are supported by the maintenance toolchain.

License

MIT

Related Packages

vue3-carousel-3d

Beautiful, flexible and touch supported 3D Carousel for Vue.js

26,162 19
@nanoandrew4/vue3-carousel-3d

Beautiful, flexible and touch supported 3D Carousel for Vue.js

13,674 4
dw-carousel-3d

Beautiful, flexible and touch supported 3D Carousel for Vue.js

3,749
vue-carousel-3d-vue3

Beautiful, flexible and touch supported 3D Carousel for Vue.js

1,050 979
@jambonn/vue-carousel

A flexible, responsive, touch-friendly carousel for Vue.js

902

Version History

Version Released License
2.1.1 MIT
2.1.0 MIT
2.0.0 MIT
1.2.1 MIT
1.2.0 MIT
Pre-releases (1)
Version Released License
2.0.0-beta.1 MIT