Vue JS Carousel with Multiple Items

Vue JS Carousel with Multiple Items
Project: Vue card carousel
Author: Will
Edit Online: View on CodePen
License: MIT

This Vue JS component implements a carousel with multiple items. It allows you to display a set of cards in a carousel layout and navigate through them using left and right navigation buttons. The carousel supports displaying multiple items at once, controlled by the `windowSize` parameter. Each card contains an image, a name, and one or more tags.

The carousel component provides functionality to move the carousel in either direction by a fixed pagination factor. It disables navigation buttons when the carousel is at the beginning or end of the list to prevent scrolling beyond the available items. This code is helpful for developers who want to incorporate a responsive and interactive carousel with multiple items into their Vue.js projects.

How to Create Vue Js Carousel With Multiple Items

First of all, load the Normalize CSS and Google Fonts by adding the following CDN links into the head tag of your HTML document.

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400" rel="stylesheet"/>

Now, create the HTML structure for the carousel as follows:

<template id="v-carousel">
  <div class="card-carousel-wrapper">
    <div class="card-carousel--nav__left" @click="moveCarousel(-1)" :disabled="atHeadOfList"></div>
    <div class="card-carousel">
      <div class="card-carousel--overflow-container">
        <div class="card-carousel-cards" :style="{ transform: 'translateX(' + currentOffset + 'px)'}">
          <div class="card-carousel--card" v-for="item in items">
            <img :src="item.image"/>
            <div class="card-carousel--card--footer">
              <p>{{ item.name }}</p>
              <p class="tag" v-for="(tag, index) in item.tag" :class="index > 0 ? 'secondary' : ''">{{ tag }}</p>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="card-carousel--nav__right" @click="moveCarousel(1)" :disabled="atEndOfList"></div>
  </div>
</template>

<div id="app">
  <carousel></carousel>
</div>

Style the image carousel using the following CSS styles:

body {
  background: #f8f8f8;
  font-family: "Source Sans Pro", sans-serif;
}
.card-carousel-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 20px 0 40px;
  color: #666a73;
}

.card-carousel {
  display: flex;
  justify-content: center;
  width: 640px;
}
.card-carousel--overflow-container {
  overflow: hidden;
}
.card-carousel--nav__left, .card-carousel--nav__right {
  display: inline-block;
  width: 15px;
  height: 15px;
  padding: 10px;
  box-sizing: border-box;
  border-top: 2px solid #42b883;
  border-right: 2px solid #42b883;
  cursor: pointer;
  margin: 0 20px;
  transition: transform 150ms linear;
}
.card-carousel--nav__left[disabled], .card-carousel--nav__right[disabled] {
  opacity: 0.2;
  border-color: black;
}
.card-carousel--nav__left {
  transform: rotate(-135deg);
}
.card-carousel--nav__left:active {
  transform: rotate(-135deg) scale(0.9);
}
.card-carousel--nav__right {
  transform: rotate(45deg);
}
.card-carousel--nav__right:active {
  transform: rotate(45deg) scale(0.9);
}

.card-carousel-cards {
  display: flex;
  transition: transform 150ms ease-out;
  transform: translatex(0px);
}
.card-carousel-cards .card-carousel--card {
  margin: 0 10px;
  cursor: pointer;
  box-shadow: 0 4px 15px 0 rgba(40, 44, 53, 0.06), 0 2px 2px 0 rgba(40, 44, 53, 0.08);
  background-color: #fff;
  border-radius: 4px;
  z-index: 3;
  margin-bottom: 2px;
}
.card-carousel-cards .card-carousel--card:first-child {
  margin-left: 0;
}
.card-carousel-cards .card-carousel--card:last-child {
  margin-right: 0;
}
.card-carousel-cards .card-carousel--card img {
  vertical-align: bottom;
  border-top-left-radius: 4px;
  border-top-right-radius: 4px;
  transition: opacity 150ms linear;
  user-select: none;
}
.card-carousel-cards .card-carousel--card img:hover {
  opacity: 0.5;
}
.card-carousel-cards .card-carousel--card--footer {
  border-top: 0;
  padding: 7px 15px;
}
.card-carousel-cards .card-carousel--card--footer p {
  padding: 3px 0;
  margin: 0;
  margin-bottom: 2px;
  font-size: 19px;
  font-weight: 500;
  color: #2c3e50;
  user-select: none;
}
.card-carousel-cards .card-carousel--card--footer p.tag {
  font-size: 11px;
  font-weight: 300;
  padding: 4px;
  background: rgba(40, 44, 53, 0.06);
  display: inline-block;
  position: relative;
  margin-left: 4px;
  color: #666a73;
}
.card-carousel-cards .card-carousel--card--footer p.tag:before {
  content: "";
  float: left;
  position: absolute;
  top: 0;
  left: -12px;
  width: 0;
  height: 0;
  border-color: transparent rgba(40, 44, 53, 0.06) transparent transparent;
  border-style: solid;
  border-width: 8px 12px 12px 0;
}
.card-carousel-cards .card-carousel--card--footer p.tag.secondary {
  margin-left: 0;
  border-left: 1.45px dashed white;
}
.card-carousel-cards .card-carousel--card--footer p.tag.secondary:before {
  display: none !important;
}
.card-carousel-cards .card-carousel--card--footer p.tag:after {
  content: "";
  position: absolute;
  top: 8px;
  left: -3px;
  float: left;
  width: 4px;
  height: 4px;
  border-radius: 2px;
  background: white;
  box-shadow: 0px 0px 0px #004977;
}

h1 {
  font-size: 3.6em;
  font-weight: 100;
  text-align: center;
  margin-bottom: 0;
  color: #333;
}

Load the Vue.js framework by adding the following CDN link just before closing the body tag.

<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js'></script>

Finally, add the following JavaScript code to your project.

Vue.component("carousel", {
    template: "#v-carousel",
    data() {
      return {
        currentOffset: 0,
        windowSize: 3,
        paginationFactor: 220,
        items: [
          {
            name: 'Kin Khao',
            image: 'https://source.unsplash.com/200x200?girl',
            tag: ["Thai"]
          },
          {
            name: 'Jū-Ni',
            image: 'https://source.unsplash.com/200x200?natural',
            tag: ["Sushi", "Japanese", "$$$$"]
          },
          {
            name: 'Delfina',
            image: 'https://source.unsplash.com/200x200?beautiful',
            tag: ["Pizza", "Casual"]
          },
          {
            name: 'San Tung',
            image: 'https://source.unsplash.com/200x200?attraction',
            tag: ["Chinese", "$$"]
          },
          {
            name: 'Anchor Oyster Bar',
            image: 'https://source.unsplash.com/200x200?rose',
            tag: ["Seafood", "Cioppino"]
          },
          {
            name: 'Locanda',
            image: 'https://source.unsplash.com/200x200?beach',
            tag: ["Italian"]
          },
          {
            name: 'Garden Creamery',
            image: 'https://source.unsplash.com/200x200?forest',
            tag: ["Ice cream"]
          }
        ]
      }
    },
    computed: {
      atEndOfList() {
        return this.currentOffset <= (this.paginationFactor * -1) * (this.items.length - this.windowSize);
      },
      atHeadOfList() {
        return this.currentOffset === 0;
      },
    },
    methods: {
      moveCarousel(direction) {
        if (direction === 1 && !this.atEndOfList) {
          this.currentOffset -= this.paginationFactor;
        } else if (direction === -1 && !this.atHeadOfList) {
          this.currentOffset += this.paginationFactor;
        }
      },
    }
  });

  new Vue({
    el: "#app"
  });

That’s all! hopefully, you have successfully created carousel with multiple items. If you have any questions or suggestions, feel free to comment below.

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply