Carousel with Vanilla JavaScript
Tags: javascript, webdev, tutorial
Published: 2020-02-01 03:36:44

Hi Guys Good Day!

Today we're gonna make a Carousel using Vanilla JavaScript.  Most of my posts we're about fundamentals and concepts and I've realized I haven't made a post about Implementing stuff or something like that. So today I'm gonna change that. So I've decided to make this post because as of now I'm currently finding a new job and one of the companies that I've applied to has an exam. And in that exam, one of the functionalities that I have to make is an Image Carousel and one of the rules of the exam is that I have to implement it without using existing javascript carousel libraries instead I have to choose one of these technologies that I'm gonna use for the Carousel. __React__, __jQuery__, __Angular__ and __Vue__. I choose __React__ because I love working with __React__ and I want to finish the exam fast. So now, I want to implement it using with just JavaScript. Let's get to the coding stuff.


Our _images_ taken from [pexels.com](https://www.pexels.com/).

_1.jpeg_
![Image 1](https://dev-to-uploads.s3.amazonaws.com/i/x1x4lh6vq7yodiwopu4s.jpeg)
_2.jpeg_
![Image 2](https://dev-to-uploads.s3.amazonaws.com/i/8mda4fq82y80693i1zrs.jpeg)
_3.jpeg_
![Image 3](https://dev-to-uploads.s3.amazonaws.com/i/u7n84gmtznpk11p1krcd.jpeg)

Our _index.html_ file.
```html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Carousel using Vanilla JS</title>
  <link href="./styles.css">
</head>

<body>
  <div class="carousel">
    <div class="arrow-left">
      <span class="arrow">&#x2039;</span>
    </div>
    <img src="./1.jpeg" alt="Carousel Image">
    <div class="arrow-right">
      <span class="arrow">&#x203A;</span>
    </div>
    <div class="indicators">
      <span class="active"></span>
      <span></span>
      <span></span>
    </div>
  </div>

  <script type="text/javascript" src="./carousel.js"></script>
</body>
</html>
```
This the primary structure of our html. All the elements that we use are inside the <code>div</code> element with a class of _carousel_.

Our _styles.css_ file.
```css
.arrow {
  font-size: 51px;
  font-weight: bold;
  border-radius: 50%;
  width: 50px;
  height: 65px;
  color: white;
  text-align: center;
  display: inline-block;
  transition: all 0.3s ease;
}

.arrow:hover {
  color: #121212;
  background: white;
  cursor: pointer;
}


.carousel {
  position: relative;
  display: block;
  width: 600px;
  margin: 0 auto;
  margin-top: 5%;
}

.arrow-left {
  position: absolute;
  left: 0;
  top: 50%;
  margin-left: 5px;
  transform: translateY(-50%);
}

.arrow-right {
  position: absolute;
  right: 0;
  top: 50%;
  margin-right: 5px;
  transform: translateY(-50%);
}

.carousel>img {
  width: 100%;
  height: 450px;
  border-radius: 4px;
}

.d-none {
  display: none;
}

.indicators {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 0;
  margin-bottom: 10px;
}

.indicators>span {
  display: inline-block;
  border-radius: 50%;
  width: 20px;
  height: 20px;
  background: white;
}

.indicators>span.active {
  background: #4fc355;
}
```

I'm not pretty good with my css skills (__sorry__), so bear with me our _carousel_ <code>div</code> element has a <code>position: relative;</code> style, so that we can position our arrows and indicators in the correct positions using the <code>position: absolute</code> inside the our _carousel_ container.


So let's take a look at our _carousel.js_ file. So, I'm gonna divide our _js_ file into multiple sections so I can explain it clearly.

__First Section__ 

```js
const arrowLeft = document.querySelector('.arrow-left');
const arrowRight = document.querySelector('.arrow-right');
const imgCarousel = document.querySelector('img');
const indicators = document.querySelectorAll('.indicators > span');
const images = ['./1.jpeg', './2.jpeg', './3.jpeg'];
```
The first part is declaring and selecting the elements that we gonna use in our 
carousel. I use the <code>document.querySelector</code> and <code>document.querySelectorAll</code> method in the <code>document</code> object because it's more flexible than the other method in the document object for
selecting elements. And our <code>images</code> variable which holds the __relative paths__  of our images, assuming we have the same files. You can change these filenames depending in your files.



__Second Section__
```js

const setAttr = (el, attr, value) => el.setAttribute(attr, value);
const getAttr = (el, attr) => el.getAttribute(attr);

const getImageIndex = (image) => images.indexOf(image)

const getCurrentImageIndex = () => {
  const currentImage = getAttr(imgCarousel, 'src');
  return getImageIndex(currentImage);
};

const getArrowLeftImageIndex = (currentIndex) => {
  return currentIndex === 0 ? 2 : currentIndex - 1;
};

const getArrowRightImageIndex = (currentIndex) => {
  return currentIndex === 2 ? 0 : currentIndex + 1;
};

const activateIndicator = (index) => {
  indicators.forEach((el, i) => {
    if (el.classList.contains('active')) {
      el.classList.remove('active')
    };
    if (index === i) el.classList.add('active');
  })
};
```
Our _helper functions_. The first two functions are used for _setting_ and _getting_ respectively the attribute of the element we want. In this case, will be the <code>img</code> element. The third function is pretty straightforward it's for getting the index of the image. The fourth function is pretty much the same as the third the difference is that here is that we _get_ the __image source__ here and call the <code>getImageIndex</code> function and return the result. The fourth function <code>getArrowLeftImageIndex</code> is used for clicking the left arrow and fifth function <code>getArrowRightImageIndex</code>
is used for clicking the right arrow. And lastly the <code>activateIndicator</code> function is used for updating the correct indicator's class.



__Third Section__
```js
const intervalSlider = (direction, delay = 1000) => {
  let callback = null, getNewIndexFunc = null;
  if (direction === 'left') {
    getNewIndexFunc = () => getArrowLeftImageIndex(getCurrentImageIndex());

  } else {
    getNewIndexFunc = () => getArrowRightImageIndex(getCurrentImageIndex());
  }

  callback = () => {
    let newIndex = getNewIndexFunc();
    activateIndicator(newIndex);
    setAttr(imgCarousel, 'src', images[newIndex]);
  }

  return () => setInterval(callback, delay);
}
```
So our third section is just one function. This function is used for sliding functionality of our carousel. Basically what this function does is that when we pass the <code>direction</code> parameter with a value of <code>"left"</code> we're gonna get the function that calculates the image index when clicking
the _left (<)_ arrow and we're gonna use that function inside the <code>callback</code> to calculate the new index of the previous image and update the correct indicator and the correct image based on the <code>newIndex</code>.
If we pass a value of <code>"right"</code> for the <code>direction</code>
parameter we're gonna get the function that calculates the next image when clicking the _right (>)_ arrow. The <code>intervalSlider</code> returns the interval that we're gonna use inside our click events and also you can change
the <code>delay</code> but my default is 1 second.


__Fourth Section__

```js

const leftInterval = intervalSlider('left');
const rightInterval = intervalSlider('right');

let left = null, right = null;

arrowLeft.addEventListener('click', (e) => {
  const newIndex = getArrowLeftImageIndex(getCurrentImageIndex());
  activateIndicator(newIndex);
  right && clearInterval(right);
  if (!left) {
    left = leftInterval()
  }
  setAttr(imgCarousel, 'src', images[newIndex]);
});
arrowRight.addEventListener('click', (e) => {
  const newIndex = getArrowRightImageIndex(getCurrentImageIndex());
  activateIndicator(newIndex);

  left && clearInterval(left);
  if (!right) {
    right = rightInterval();
  }
  setAttr(imgCarousel, 'src', images[newIndex]);
});
```

Lastly, our fourth section. First we declare the functions that returns the interval and we have the <code>left</code> and <code>right</code> variables to hold the interval so that we can use them later in our click events. So in our <code> arrowLeft</code> click event callback, we get the new index
specifically the previous index of the current index, after that we call the <code>activateIndicator</code> function passing the <code>newIndex</code>. If we have an interval value for the <code>right</code> value, we're gonna clear 
that interval using the <code>clearInterval</code> function. After that, if our <code>left</code> variable does not have a value, we're gonna start the interval using the <code>leftInterval</code> and lastly we're gonna update the 
image. In our <code>arrowRight</code> click event callback has almost have the same logic as the <code>arrowLeft</code> click event callback, but in the <code>arrowRight</code> we get the next index of the current index and also we're 
gonna clear the interval of the <code>left</code> variable if it has a value and start the <code>right</code> interval if it's not already started. After that, update the image.


You can add additional functionalities to this carousel, like __pausing__ or anything that comes up in your mind.  

##Thanks guys for reading this post.
# Have a Nice Day :smiley:!.