How to make a card carousel with CSS & JS
Tags: webdev, tutorial, css, javascript
Published: 2023-01-12 01:30:13

##Table of contents 
* [How it works](#How-it-works)
* [HTML & CSS](#Layout)
* [Javascript](#Carousel)
* [Hover Effect](#Hover)
* [Color change click event](#Extra)
* [Conclusion](#Conclusion)

#How it works<a name="How-it-works"></a>
This blog might be a bit complicated so here's an overview of how it works. We'll be making a carousel with cards (that are just div with images) and a div called card-selector. The card selector will reveal the card that the user chooses to see using the left and right buttons. To illustrate what I just said look at the gif below. The blue box is the card carousel and the red box is the card selector. The card selector or red box is where the card will be shown, so to make sure the others aren't seen yet we just set the card selectors `overflow` to `hidden` and on the codepen below you can see the results.



![blub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s2au3vu88v9qz2dhloqk.gif)





{% codepen https://codepen.io/lensco825/pen/xxJRmMX %}

<hr>

## HTML and CSS<a name="Layout"></a>
First, we'll go over the basic HTML and CSS needed. In the body element, we'll make a main element to group all the content together. In it is first a header, a left and right icon, and a div in between those icons that have a class called `card-selector`. This div will be used to show only the card that was selected. Inside the card selector is an unordered list with the class of `carousel` since it'sour carousel. Lastly inside the carousel are the carousel slides that have the cards, the first carousel slide will have the `shownCard` class so it's the first card shown, it'll also be useful for the javascript later.
```html
  <main>
    <h1>5 things i like</h1>
    <ion-icon name="chevron-back-outline" class="button-backwards"></ion-icon>
  <div class="card-selector">
    <ul class="carousel">
      <li class="carousel_slide shownCard">
        <div id="Cards" class="firstCard"></div>
      </li>
      <li class="carousel_slide">
        <div id="Cards" class="secondCard"></div>
      </li>
      <li class="carousel_slide">
        <div id="Cards" class="thirdCard"></div>
      </li>
      <li class="carousel_slide"><div id="Cards" class="fourthCard">
      </div></li>
      <li class="carousel_slide">
        <div id="Cards" class="fifthCard"></div>
      </li>
    </ul>
  </div>
    <ion-icon name="chevron-forward-outline" class="button-forward"></ion-icon>
  </main>
```
<br>
For the CSS we center everything by giving the body a `display` of `flex` and giving `align-items` and `justify-content` a value of `center`. For my ul element or carousel, we give it a `width` and `height` of `250px` and a `display` of `flex` to center the cards. We also set the `list-style-type` to none so we don't have those li discs remaining in it. We give the carousel slides a position of absolute while giving the carousel a position relative to stack the slides on top of each other. We make the slides the same size as the card container and give them flex to center their div cards. We'll also make sure they're in the container by setting their `top` and `bottom` to `0`. The left and right buttons have an absolute position to use the `top` `left` and `right` properties to place them. Finally, I gave each card a `background-image`. 
```css
.card-selector {
  margin: 0 auto;
  padding: 0;
  border: solid 2px red;
}

.carousel {
  position: relative;
}


.carousel_slide {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 250px;
  height: 250px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: solid 2px blue;
}

/*Styling the buttons*/
ion-icon {
  font-size: 40px;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  z-index: 3;
  color: white;
}

.button-backwards {
left: 30%;
  top: 50%;
}

.button-forward {
  right: 30%;
  top: 50%;
}
/*Styling the cards*/
#Cards {
  width: 100px;
  height: 150px;
  transition: 0.4s;
  background-size: cover;
}

}

```
<hr>
## Javacript<a name="Carousel"></a>
First, we make variables containing the carousel and button, we also make a variable with an array of the carousel's children, this is how we get all the carousel slides. Another variable we'll make is a variable called `cardSize` which has the width **boundingClientReact** of the cards. The BoundingClientReact is a method used to get information and the size width and height of an element, so since we gave the cardSize variable a value of `cards[0].getBoundingClientReact().width` we now stored the width of the slides in that variable. 

```js
var carousel = document.querySelector('.carousel');
var carousel_slide = Array.from(carousel.children);
var nextButton = document.querySelector('.button-forward');
var backButton = document.querySelector('.button-backwards');
var cardSize = carousel_slide[0].getBoundingClientRect().width;
```
The cards will now have a `forEach` method where in it is an arrow function that stylizes the left property value of the carousel slides to be the cardSize variable * the index. This makes it so the carousel slides aren't on top of each other but are side by side. Here's an image to show you, the blue boxes are the carousel slides.

```js
carousel_slide.forEach((slide, index) => {
  slide.style.left = cardSize * index + 'px';
})
```
![carousel](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hbbng5pqvsc3dp4u3edg.png)

Now for the buttons, we'll make an arrow function called `moveToCard` with the carousel, `targetCard` and `currentCard` being its parameters to shorten the code for the event listeners of the buttons. The target card will be the card that'll be shown next, while the current card is the card that's being seen. We'll make it so the card container translates on the X-axis by the left property value of the target card. Next, we make it so the shownCard class will be removed from the current card and will be added to the target card so the function can run more than once. 

```js
const moveToCard = (carousel, currentCard, targetCard) => {
  carousel.style.transform = 'translateX(-' + targetCard.style.left + ')';
  currentCard.classList.remove('shownCard');
  targetCard.classList.add('shownCard');
}
```
Next, we'll make the button event listeners that'll use the MovetoCard function. We make two variables with one having the shownCard class and the other being the target card. The target card in each event listener will be different because the next button's event listener will have the current card's `nextElementSibling` while the previous button will have the current card's `previousElementSibling`. Finally, we call the function with the currentCard parameter being the variable with the shownCard class and the targetCard being the card with the currentCard's sibling.

```js

nextButton.addEventListener('click', function() {
const currentCard = document.querySelector('.shownCard');
const targetCard = currentCard.nextElementSibling;
  moveToCard(carousel, currentCard, targetCard);
});


backButton.addEventListener('click', function() {
const currentCard = document.querySelector('.shownCard');
const prevCard = currentCard.previousElementSibling;
  moveToCard(carousel, currentCard, prevCard);
});

```
<br>
Now when we click the forward/next button we go to the current cards next element sibling wich becomes the current card. If we click the previous button we go to the previous carousel slide element wich becomes the current card. Now that we made the card carousel we can make cool transitions and effects.

<hr>
#Hover effects<a name="Hover"></a>
We gave each card a hover effect where their before pseudo-element goes from invisible to visible. We did this by setting the before pseudo-class to `display: none;` but when the card is hovered, it'll transition up. Lastly, we gave each card a different content based on how they look.

```css
.carousel_slide > div::before {
  display: none;
}


.carousel_slide > div:hover::before {
  position: relative;
  top: 170px;
  left: 24px;
   color: white;
   font-size: 20px;
  transition: 0.5s;
  display: block;
  font-family: 'Courier New', Courier, monospace;
}
```
<hr>
#Color change JS<a name="Extra"></a>
This section is about how i made it so when you click a card the color of the website changes. First we put all the cards in a variable as an array. Then we give each card an event listener where when their clicked, they'll change the background-color to a certain color that matches their card.

```js
var card = Array.from(document.querySelectorAll('#Cards'));

card[0].addEventListener('click', function() {
  document.body.style.backgroundColor = '#FADBBEff';
})

card[1].addEventListener('click', function() {
  document.body.style.backgroundColor = '#bc6c25';
})

card[2].addEventListener('click', function() {
  document.body.style.background = '#6905BBff';
})

card[3].addEventListener('click', function() {
  document.body.style.background = '#2a9d8f';
})

card[4].addEventListener('click', function() {
  document.body.style.backgroundColor = '#ff7d00';
})

```
<br>
#Conclusion<a name="Conclusion"></a>
Even though i started making this blog a week ago it took so long because of the way i named by variables and classes since they were confusing and irrelavent to their actual use, but after a while i fixed the code so it can be easier for you to understand. I'm also sorry if this blog is too long or complicated, so if you have an questions or want change's in my blog please tell them in the comments! You can also show me the card carousel you made in the comments, so with all said and done i hope you have a great day or night!