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. With over 12 years of Vue.js development experience since 2014 and 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'><</button>
<button @click='next' class='carousel-btn next'>></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.



