One data grid for JavaScript, React, Vue & Angular. Sorting, filtering, virtualization, pinning, and CSV export included. Early access $199 $349 → [Get it now]

How to build a carousel in Vue

Image carousels are essential UI components for showcasing multiple images or content cards in a compact, interactive format. As the creator of CoreUI, I’ve built numerous carousel implementations for e-commerce and portfolio sites. A basic Vue carousel requires reactive state for the current slide index, methods for navigation, and CSS for slide positioning. This approach creates a fully functional carousel without external dependencies.

Build a carousel using reactive state, computed properties, and CSS transforms for slide transitions.

<template>
  <div class='carousel'>
    <div class='carousel-inner' :style='{ transform: `translateX(-${currentIndex * 100}%)` }'>
      <div v-for='(slide, index) in slides' :key='index' class='carousel-slide'>
        <img :src='slide.image' :alt='slide.title'>
      </div>
    </div>
    <button @click='prev' class='carousel-btn prev'>&lt;</button>
    <button @click='next' class='carousel-btn next'>&gt;</button>
    <div class='carousel-dots'>
      <span
        v-for='(_, index) in slides'
        :key='index'
        :class='{ active: index === currentIndex }'
        @click='currentIndex = index'
      ></span>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const slides = ref([
  { image: '/img1.jpg', title: 'Slide 1' },
  { image: '/img2.jpg', title: 'Slide 2' },
  { image: '/img3.jpg', title: 'Slide 3' }
])

const currentIndex = ref(0)

const next = () => {
  currentIndex.value = (currentIndex.value + 1) % slides.value.length
}

const prev = () => {
  currentIndex.value = currentIndex.value === 0 ? slides.value.length - 1 : currentIndex.value - 1
}
</script>

<style scoped>
.carousel {
  position: relative;
  overflow: hidden;
  width: 100%;
}

.carousel-inner {
  display: flex;
  transition: transform 0.3s ease;
}

.carousel-slide {
  min-width: 100%;
}

.carousel-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 10;
}

.prev { left: 10px; }
.next { right: 10px; }

.carousel-dots {
  text-align: center;
  padding: 10px;
}

.carousel-dots span {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #ccc;
  margin: 0 5px;
  cursor: pointer;
}

.carousel-dots span.active {
  background: #333;
}
</style>

Best Practice Note

Add autoplay functionality using setInterval in an onMounted hook, and clear it in onUnmounted to prevent memory leaks. For touch devices, add swipe support using touch event listeners. Consider using CoreUI for Vue which includes production-ready carousel components with additional features like lazy loading and keyboard navigation at CoreUI Vue Components.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
What Does javascript:void(0) Mean?
What Does javascript:void(0) Mean?

How to Detect a Click Outside of a React Component
How to Detect a Click Outside of a React Component

CSS Selector for Parent Element
CSS Selector for Parent Element

How to Convert a Map to an Array in JavaScript
How to Convert a Map to an Array in JavaScript

Answers by CoreUI Core Team