logo

Simple Vue Carousel Component

If you're in need of a carousel component for your Vue project without resorting to libraries like Swiper, this post introduces a straightforward component using Vue and Tailwindcss.

Note!
We assume you have created vue project and have tailwindcss installed.

First, we need to create component. In this example we named it SimpleCarousel.vue and then write the code as below:

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

const carousel = ref();

const scrollTo = (direction) => {
  const { width } = carousel.value.getBoundingClientRect();
  let scrollLeft = carousel.value.scrollLeft;
  scrollLeft = direction === 'left' ? scrollLeft - width : scrollLeft + width;
  carousel.value.scroll({
    left: scrollLeft,
    behavior: 'smooth',
  });
}
</script>

<template>
  <div class="relative">
    <button
      class="border shadow-md bg-white p-2 rounded-full z-20 absolute top-1/2 -left-5 -translate-y-1/2 transform transition motion-safe:hover:scale-110 duration-500"
      @click="scrollTo('left')">
      <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
        <path d="M13.36 17a1 1 0 0 1-.72-.31l-3.86-4a1 1 0 0 1 0-1.4l4-4a1 1 0 1 1 1.42 1.42L10.9 12l3.18 3.3a1 1 0 0 1 0 1.41 1 1 0 0 1-.72.29z" />
      </svg>
    </button>
    <div ref="carousel" class="flex overflow-x-auto">
      <div class="flex gap-4 m-[3px]">
        <slot></slot>
      </div>
    </div>
    <button
      class="border shadow-md bg-white p-2 rounded-full z-20 absolute top-1/2 -right-5 -translate-y-1/2 transform transition motion-safe:hover:scale-110 duration-500"
      @click="scrollTo('right')">
      <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
        <path d="M10.5 17a1 1 0 0 1-.71-.29 1 1 0 0 1 0-1.42L13.1 12 9.92 8.69a1 1 0 0 1 0-1.41 1 1 0 0 1 1.42 0l3.86 4a1 1 0 0 1 0 1.4l-4 4a1 1 0 0 1-.7.32z" />
      </svg>
    </button>
  </div>
</template>

    
src/components/SimpleCarousel.vue

Then we can use it in any vue file

    <script setup>
import SimpleCarousel from '@/components/SimpleCarousel.vue';
</script>

<template>
  <p class="mb-2 font-semibold">Product Carousel</p>
  <simple-carousel>
    <div v-for="item in data" :key="item.id">
      <!-- your item here -->
    </div>
  </simple-carousel>
</template>

    

We can add conditional statement to show or hide arrow button. Left arrow button will hide if the scroll width less than 0 and will shown if the right button pressed or scroll width grather than 0. Otherwise, the right button will hide if the carousel reach the end.

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

const carousel = ref();
const showLeftButton = ref(false); const showRightButton = ref(true); 
const scrollTo = (direction) => {
  const { width } = carousel.value.getBoundingClientRect();
  const scrollWidth = carousel.value.scrollWidth;   let scrollLeft = carousel.value.scrollLeft;
  scrollLeft = direction === 'left' ? scrollLeft - width : scrollLeft + width;
  carousel.value.scroll({
    left: scrollLeft,
    behavior: 'smooth',
  });
  showLeftButton.value = scrollLeft > 0;   showRightButton.value = scrollLeft < scrollWidth - width; }
</script>

<template>
  <div class="relative">
    <button
      v-if="showLeftButton"
       class="border shadow-md bg-white p-2 rounded-full z-20 absolute top-1/2 -left-5 -translate-y-1/2 transform transition motion-safe:hover:scale-110 duration-500"
      @click="scrollTo('left')">
      <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
        <path d="M13.36 17a1 1 0 0 1-.72-.31l-3.86-4a1 1 0 0 1 0-1.4l4-4a1 1 0 1 1 1.42 1.42L10.9 12l3.18 3.3a1 1 0 0 1 0 1.41 1 1 0 0 1-.72.29z" />
      </svg>
    </buton>
    <div ref="carousel" class="flex overflow-x-auto">
      <div class="flex gap-4 m-[3px]">
        <slot></slot>
      </div>
    </div>
    <button
      v-if="showRightButton"
      class="border shadow-md bg-white p-2 rounded-full z-20 absolute top-1/2 -right-5 -translate-y-1/2 transform transition motion-safe:hover:scale-110 duration-500"
      @click="scrollTo('right')">
      <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
        <path d="M10.5 17a1 1 0 0 1-.71-.29 1 1 0 0 1 0-1.42L13.1 12 9.92 8.69a1 1 0 0 1 0-1.41 1 1 0 0 1 1.42 0l3.86 4a1 1 0 0 1 0 1.4l-4 4a1 1 0 0 1-.7.32z" />
      </svg>
    </button>
  </div>
</template>

    
src/components/SimpleCarousel.vue

Add style to hide horizontal scrollbar

    @tailwind base;
@tailwind components;
@tailwind utilities;

@layer utilities {
  /* Hide scrollbar for Chrome, Safari and Opera */
  .hide-scrollbar::-webkit-scrollbar {
    display: none;
  }

  /* Hide scrollbar for IE, Edge and Firefox */
  .hide-scrollbar {
    -ms-overflow-style: none;  /* IE and Edge */
    scrollbar-width: none;  /* Firefox */
  }
}

    
assets/tailwind.css

Apply style to SimpleCarousel.vue component.

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

const carousel = ref();
const showLeftButton = ref(false);
const showRightButton = ref(true);

const scrollTo = (direction) => {
  const { width } = carousel.value.getBoundingClientRect();
  const scrollWidth = carousel.value.scrollWidth;
  let scrollLeft = carousel.value.scrollLeft;
  scrollLeft = direction === 'left' ? scrollLeft - width : scrollLeft + width;
  carousel.value.scroll({
    left: scrollLeft,
    behavior: 'smooth',
  });
  showLeftButton.value = scrollLeft > 0;
  showRightButton.value = scrollLeft < scrollWidth - width;
}
</script>

<template>
  <div class="relative">
    <button
      v-if="showLeftButton"
       class="border shadow-md bg-white p-2 rounded-full z-20 absolute top-1/2 -left-5 -translate-y-1/2 transform transition motion-safe:hover:scale-110 duration-500"
      @click="scrollTo('left')">
      <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
        <path d="M13.36 17a1 1 0 0 1-.72-.31l-3.86-4a1 1 0 0 1 0-1.4l4-4a1 1 0 1 1 1.42 1.42L10.9 12l3.18 3.3a1 1 0 0 1 0 1.41 1 1 0 0 1-.72.29z" />
      </svg>
    </buton>
    <div ref="carousel" class="flex overflow-x-auto">    <div ref="carousel" class="flex overflow-x-auto hide-scrollbar">      <div class="flex gap-4 m-[3px]">
        <slot></slot>
      </div>
    </div>
    <button
      v-if="showRightButton"
      class="border shadow-md bg-white p-2 rounded-full z-20 absolute top-1/2 -right-5 -translate-y-1/2 transform transition motion-safe:hover:scale-110 duration-500"
      @click="scrollTo('right')">
      <svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
        <path d="M10.5 17a1 1 0 0 1-.71-.29 1 1 0 0 1 0-1.42L13.1 12 9.92 8.69a1 1 0 0 1 0-1.41 1 1 0 0 1 1.42 0l3.86 4a1 1 0 0 1 0 1.4l-4 4a1 1 0 0 1-.7.32z" />
      </svg>
    </button>
  </div>
</template>

    
src/components/SimpleCarousel.vue

Simple Vue Carousel Component


Now you have a simple Vue carousel component with Tailwindcss that enhances user experience without relying on external libraries. Feel free to customize and adapt this component to fit your project's needs.

Demo
Source code

Related posts

Deploy Vue Project to Github Pages

14 May 2022

Deploy Vue Project to Github Pages

Deploy your Vue project to GitHub Pages effortlessly by automating the deployment process with Vue to GitHub Pages

Create Infinite Scroll in Vue

17 March 2022

Create Infinite Scroll in Vue

Enhance website navigation with Vue.js by implementing user-friendly infinite scroll without additional package