Simple JS carousel tutorial
Aug 22, 2022, 2:12 PM
Brazillian Furry tech wizard explains his javascript carousel source code in detail and makes a tutorial out of it.
tech
.webp)
Before reading it further:
If you just want to see the source code check the github repo at the end of the article.
If you find something you've never seen before, search for it on websites like W3 Schools or Mozilla Docs
Here's what the final result will look like:
HTML
First let's begin by taking a look at our html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./css/styles.css">
<title>epic</title>
<script src="./js/carousel.js"></script>
</head>
<body>
<h1>epic</h1>
<article class="container">
<section id="carousel">
<a class="imagecontainer" href="">
<img src="img/1.gif" alt="gif">
</a>
<a class="imagecontainer" href="">
<img src="img/2.gif" alt="gif">
</a>
<a class="imagecontainer" href="">
<img src="img/3.gif" alt="gif">
</a>
<a class="imagecontainer" href="">
<img src="img/4.gif" alt="gif">
</a>
<a class="imagecontainer" href="">
<img src="img/5.gif" alt="gif">
</a>
<a class="imagecontainer" href="">
<img src="img/6.gif" alt="gif">
</a>
</section>
<button id="btnright"></button>
<button id="btnleft"></button>
</article>
</body>
</html>
Lest take a look at the components of the body one by one:
<article class="container">
Is just used to center the carousel and it's buttons in the page.
<section id="carousel">
Is the actual carousel and also where we will put all the images inside.
<a class="imagecontainer" href="">
Is a hyperlink tag that will contain the images, and it will allow you to use it's href attribute to redirect the user to another page after clicking the image for example.
<img src="img/6.gif" alt="gif">
Is just the image inside each container.
<button id="btnleft></button>
Is the left button
<button id="btnright"></button>
Is the right button
And that sums up the HTML (honestly it ins't like there is a lot to talk about anyway).
The CSS
Now let's take a look at the CSS:
@font-face {
font-family: "Sauce Code Pro";
src: url(../Sauce\ Code\ Pro\ Nerd\ Font\ Complete.ttf);
}
body {
font-family: "Sauce Code Pro";
text-align: center;
margin: 0vw 10vw;
}
.container {
overflow: hidden;
border-radius: 20px;
position: relative;
height: fit-content;
}
button {
font-family: "Sauce Code Pro" !important;
}
#carousel {
background-color: #e9e9e960;
max-height: 40vw;
max-height: 500px;
margin: 0;
padding: 0;
display: flex;
align-items: center;
position: relative;
overflow-x: auto;
overflow-y: hidden;
scroll-behavior: smooth;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
}
#carousel::-webkit-scrollbar {
display: none;
}
#btnleft {
left: 0vw;
}
#btnright {
right: 0vw;
}
#btnright,
#btnleft {
font-family: "Sauce Code Pro";
font-size: 1.6vw;
color: #555555;
z-index: 999;
width: 3vw;
border-style: none;
position: absolute;
top: 0;
height: 100%;
background-color: #d4d4d4a4;
}
#btnright:hover,
#btnleft:hover {
color: #959595;
background-color: #dededee4;
cursor: pointer;
}
.imagecontainer {
object-fit: cover;
box-sizing: border-box;
image-rendering: auto;
height: 50vw;
min-height: 50vw;
min-width: 100%;
margin: 0;
padding: 0;
scroll-snap-align: auto;
}
.imagecontainer>img {
min-height: 50vw;
object-fit: cover;
object-position: 90% 90%;
min-width: 80vw;
}
.imagecontainer:hover {
filter: brightness(1.2);
max-height: 105%;
}
Note:
For the sake of not keeping this too long i will not explain the css line by line, that said allow me to explain the css almost line by line.
The first thing we do is importing an icon font of our choice. The one i choose can be found in this carousel's github repository and also on the nerdfonts project webpage.
There are other better ways you might want to do this, like using something like the iconify api instead. So this is something you might want to change if you implement this on your personal project.
@font-face {
font-family: "Sauce Code Pro";
src: url(../Sauce\ Code\ Pro\ Nerd\ Font\ Complete.ttf);
}
On the .container
i used position: relative;
so later we can position the buttons on it's sides.
Now let's talk about the actual carrousel:
#carousel {
background-color: #e9e9e960;
min-height: 40vw;
max-height: 500px;
margin: 0;
padding: 0;
display: flex;
align-items: center;
position: relative;
overflow-x: auto;
overflow-y: hidden;
scroll-behavior: smooth;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
}
#carousel::-webkit-scrollbar {
display: none;
}
So on the carousel we set:
margins: 0;
and paddings: 0;
so it does not offset the images inside of it.
display:flex;
so the images are displayed side by side.
overflow-x: auto;
and overflow-y:hidden;
so we can scroll them horizontally but not vertically.
scroll-behavior: smooth;
and scroll-snap-type: x mandatory;
so we have a smooth scrolling animation between the images and the images will snap horizontally if we scroll them on a touch screen.
scrollbar-width: none;
and
#carousel::-webkit-scrollbar {
display: none;
}
so we hide the scrollbar.
On #btnright
and #btnleft
i used position: absolute
, right: 0;
and left: 0;
to set their position.
On .imagecontainer
i set object-fit: cover;
so the images are cropped to fit the carousel, and scroll-snap-align: auto;
to specify that this is the element that should snap when we scroll the carousel.
On the .imagecontainer>img
i also set object-fit: cover;
.
And that's about it.
The JS:
The js code is pretty simple and well commented so you'll probably understand it just by taking a look. Anyway i still wrote some paragraphs explaining it in case you miss something.
document.addEventListener("DOMContentLoaded", () => {
//Define your variables here:
const cid = '#carousel'; //carrousel id
const imgclass = 'imagecontainer'; //images class
const btnL = '#btnleft'; //Left button id
const btnR = '#btnright'; //right button id
const timer = 2000; //timer in ms for the carousel to autoswitch, leave zero for no autoswitch;
const autoSwitchDir = 1; //direction for the carrousel to move automatically
setupCarousel(cid, imgclass, btnL, btnR, timer, autoSwitchDir);
})
/**
* This function will call the other functions, add event listener to the buttons and make te carrousel move if a timer is defined!
* @param {string} cid // Carrousel id
* @param {string} imgclass // class for the image containers
* @param {string} btnL // id for Left Button
* @param {string} btnR // id for Right Button
* @param {number} timer // time in ms between each image transition
* @param {number} autoSwitchDir // 1 or 0 or -1, direction for the image to scroll automatically if a timer is setup.
*/
function setupCarousel(cid, imgclass, btnL, btnR, timer, autoSwitchDir) {
var carousel = document.querySelector(cid);
var images = document.getElementsByClassName(imgclass);
var bLeft = document.querySelector(btnL);
var bRight = document.querySelector(btnR);
forceStartPosition(carousel, 0);
let interval = null;
if (timer > 0) {
interval = window.setInterval(move, timer, carousel, images, autoSwitchDir);
}
bRight.onclick = () => {
if (interval) {
clearInterval(interval);
}
move(carousel, images, 1);
if (timer > 0) {
interval = window.setInterval(move, timer, carousel, images, autoSwitchDir);
}
}
bLeft.onclick = () => {
if (interval) {
clearInterval(interval);
}
move(carousel, images, -1);
if (timer > 0) {
interval = window.setInterval(move, timer, carousel, images, autoSwitchDir);
}
}
}
/**
* This function is updates the position of the data-pos attribute and scrolls to the next image.
* @param {object} carousel //the carousel
* @param {object} images //images that are children of the carrosel
* @param {number} dir //the direction to move the image
*/
function move(carousel, images, dir) {
var width = images[0].offsetWidth;
var maxpos = width * images.length; //mutiply the imagewidth by the amount of images to get the total size of the carrosel
var pos = parseInt(carousel.dataset.pos);
var nextpos = pos + width * dir; //calculate next position
if (nextpos < maxpos && nextpos >= 0) {
//just move to the nextpos
pos = nextpos;
carousel.dataset.pos = pos;
carousel.scrollTo(pos, 0);
} else if (nextpos < 0) {
//wrap around to the maxpos
pos = (maxpos - width);
carousel.dataset.pos = pos;
carousel.scrollTo(pos, 0);
} else if (nextpos >= maxpos) {
// go back to start position
pos = 0;
carousel.dataset.pos = pos;
carousel.scrollTo(pos, 0);
}
}
/*
* This function forces the carousel start position to be 0 and sets the data-pos attribute for the first time to 0 aswell.
* @param {object} carousel // the carousel object
*/
function forceStartPosition(carousel) {
carousel.scrollTo(0, 0);
carousel.dataset.pos = 0;
}
First we wait for the page to be fully loaded by using the document.addEventListener("DOMContentLoaded", () => { })
function, then once it's loaded, we setup some variables for the carousel and call setupCarousel()
with them.
Then setupCarousel()
will do the following:
- Force the scrollbar position to be 0 and create a data-pos attribute on the carousel html element for storing the position.
- Create an interval for automatically switching images if we passed an timer bigger than 0.
- Add click event listeners to both buttons so once we click them we clear the interval, move the carousel and start another interval. (we reset the interval so the images don't scroll on a row if the user clicks next to the interval )
Note on html data-attributes:
Basically you can use an html element to store a variable and read it later by defining and data-attribute, we're using it because we need the position to be an universal value used by all function calls. More on data-attributes here: Mozilla docs - How to use data attributes, W3 Schools - html data-* attribute.
But how do we actually move()
the images ?
Well here's how:
- Get the image width. (all images have the same width)
- Galculate the max position of the scrollbar ( image width * number of images)
- Get our scroll position from the carousel's data-pos attribute.
- Calculate the next position ( current position + ( image width * direction)) , note that direction is or 1 or -1 here.
- If our next position is between 0 and max position we move one image to the side and update the carousel data-pos attribute.
- If our next position is less than 0 then we move to the last image of the carousel (maxpos - width) and update the carousel data-pos attribute.
- If our next position is bigger or equal to our max pos then we scroll back to the start of the carousel ( 0 ) and update the carousel data-pos attribute.
Conclusion
Now that you understand how it works, feel free to copy the source code from my github repo and use it in your projects as you see fit.
github Link!
Well that's about it. I made this to help people who are starting get a better understanding of js, html and css.
Hope it helps ~ Niii.