Build an Image Slider with Vue.js

Image Slider

A post on sub-reddit Vue.js has a link to 2helixtech.com where there is a tutorial with detailed explanations to help you build an image slider using Javascript and HTML. You are only going to need Vue and not any extra plugins.

Get started

Create a new Vue object and fill an array with images to show. You use a variable to keep the current active image.

new Vue({
    el: 'body',
    data: {
        images: ['http://i.imgur.com/vYdoAKu.jpg', 'http://i.imgur.com/PUD9HQL.jpg', 'http://i.imgur.com/Lfv18Sb.jpg', 'http://i.imgur.com/tmVJtna.jpg', 'http://i.imgur.com/ZfFAkWZ.jpg'],
        currentNumber: 0
    }
});

You can display the first image of the array by using the img tag, bind the src attribute to the images array and use the variable you have set to show the first item in the array.

<body>
    <img :src="images[currentNumber]" />
</body>

And the first image has appeared!

Image rotation

The images should slide automaticly and manually, so 2 functionalities can be implemented.Give the ability to the user to go forth and back and the images to slide on a fixed time.

new Vue({
    el: 'body',
    data: {
        images: ['http://i.imgur.com/vYdoAKu.jpg', 'http://i.imgur.com/PUD9HQL.jpg', 'http://i.imgur.com/Lfv18Sb.jpg', 'http://i.imgur.com/tmVJtna.jpg', 'http://i.imgur.com/ZfFAkWZ.jpg'],
        currentNumber: 0,
        timer: null
    },

    ready: function () {
        this.startRotation();
    },

    methods: {
        startRotation: function() {
            this.timer = setInterval(this.next, 3000);
        },

        next: function() {
            this.currentNumber += 1
        }
    }
});

Add a variable to store the time that has passed and create 2 methods. Use setInterval to run an interval after 3 seconds and next() method is called, which simply increments the currentNumber. You can use Vue's ready method to call the startRotation functio, when the page has loaded.

When the last image loads the cycle stops. That is because the next function increments the currentNumber to a number larger than the array's items. You should check if that number is greater or use the modulus operator like so:

<body>
    <img :src="images[currentNumber % images.length]" />
</body>

Then the ability to swap between images manualy is needed.

    ...

        next: function() {
            this.currentNumber += 1
        },
        prev: function() {
            this.currentNumber -= 1
        }
    }
});

We can use the already existing next function and add a new one to slide to the previous image. Both simply change the value of the variable currentNumber. Also controls for cycling images are required, which can be hooked to the next and previous functions.

<body>
    <p>
        <a @click="prev">Previous</a> || <a @click="next">Next</a>
    </p>
     <img :src="images[currentNumber % images.length]" />
</body>

With @click the user can trigger each function and slide throught the images.

But we encounter an issue with this, because of the modulus operator we might end up with negative numbers. To solve this we can use the Math.abs() function which returns the absolute value of a number.

<body>
    <p>
        <a @click="prev">Previous</a> || <a @click="next">Next</a>
    </p>
    <img :src="images[Math.abs(currentNumber) % images.length]" />
</body>

CSS transitions

To apply a pretty slide effect to our slider we can use the provided transitions system by Vue.

To apply transition effects, you need to use the special transition attribute on the target element.The transition attribute can be used together with:

  • v-if
  • v-show
  • v-for (triggered for insertion and removal)

We will call our transition fade and we need to define CSS rules for .fade-transition, .fade-enter and .fade-leave classes.

.fade-transition {
  transition: all 0.8s ease;
  overflow: hidden;
  visibility: visible;
  opacity: 1;
  position: absolute;
}
.fade-enter, .fade-leave {
  opacity: 0;
  visibility: hidden;
}

Then use v-for to cycle through each element and apply the transition with transition="fade".

<body>
    <p>
        <a @click="prev">Previous</a> || <a @click="next">Next</a>
    </p>
    <div
         v-for="number in [currentNumber]"
         transition="fade"
    >
      <img
          :src="images[Math.abs(currentNumber) % images.length]"/>
    </div>
</body>

Now we have smooth transitions between images by appliying automatic transition effects

Read the whole tutorial on 2helixtech and take a look at the final result