Skip to content

Instantly share code, notes, and snippets.

@GGrassiant
Last active October 1, 2020 21:02
Show Gist options
  • Select an option

  • Save GGrassiant/8428cb8ae9919aab628949943af84ba2 to your computer and use it in GitHub Desktop.

Select an option

Save GGrassiant/8428cb8ae9919aab628949943af84ba2 to your computer and use it in GitHub Desktop.
Vanilla JS Carousel
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Hero Slider</title>
<link rel="stylesheet" href="style/style.css" />
<link
href="https://fonts.googleapis.com/css?family=Chivo"
rel="stylesheet"
/>
</head>
<body>
<div>
<div id="wbn-slider" >
<div class="wbn-slide">
<img src="img/slide1_unsplash.jpg" />
</div>
<div class="wbn-slide">
<img src="img/slide2_unsplash.jpg" />
<div class="wbn-overlay-text">
<span class="wbn-header">HEADER TEST</span>
<span class="wbn-text">
Fusce pellentesque dui blandit, tristique lectus id, pulvinar lacus.
Suspendisse potenti. Aliquam in varius magna. Sed eleifend suscipit
eros, non consectetur enim varius quis. Sed semper semper lacus nec
porttitor.
</span>
</div>
</div>
<div class="wbn-slide active"><img src="img/slide3_unsplash.jpg" /></div>
<div class="wbn-slide"><img src="img/slide4_unsplash.jpg" /></div>
<div class="wbn-slide"><img src="img/slide5_unsplash.jpg" /></div>
<div class="wbn-buttons">
<div class="wbn-slider-back-btn">
<span>◀</span>
</div>
<div class="wbn-slider-next-btn">
<span>▶</span>
</div>
</div>
<div id="dots-container"></div>
</div>
</div>
<!-- Import the Slider -->
<script src="src/wbn-slider.js"></script>
</body>
</html>
body {
margin: 0;
padding: 0;
}
#wbn-slider {
position: relative;
height: 50vw;
overflow: hidden;
}
.wbn-slide {
position: absolute;
width: 100%;
z-index: 500;
height: 50vw;
}
.wbn-slide img {
object-fit: cover;
width: 100%;
pointer-events: none;
}
.active {
z-index: 1000;
}
.slideInLeft {
animation-name: animateInLeft;
z-index: 1000;
}
.slideInRight {
animation-name: animateInRight;
z-index: 1000;
}
.slideOutLeft {
transform: translateX(-100%);
}
.slideOutRight {
transform: translateX(100%);
}
@keyframes animateInLeft {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(0%);
}
}
@keyframes animateInRight {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(0%);
}
}
.wbn-buttons {
position: absolute;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
height: 100%;
z-index: 20000;
}
.wbn-slider-back-btn,
.wbn-slider-next-btn {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: #fff;
font-size: 20px;
opacity: 0.7;
border-radius: 50px;
width: 50px;
height: 50px;
transition: all 0.2s;
margin: 20px;
}
.wbn-slider-back-btn:hover,
.wbn-slider-next-btn:hover {
transform: scale(1.1);
opacity: 0.8;
cursor: pointer;
}
.wbn-overlay-text {
position: absolute;
display: flex;
display: -ms-flexbox;
display: -webkit-flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
color: white;
top: 0;
left: 0;
z-index: 10000;
opacity: 1;
}
.wbn-overlay-text .wbn-header {
font-family: 'Chivo', sans-serif;
font-size: 80px;
font-weight: 800;
}
.wbn-overlay-text .wbn-text {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
font-size: 22px;
line-height: 30px;
color: white;
max-width: 30%;
}
#dots-container {
position: absolute;
bottom: 5%;
left: 40%;
width: 20%;
z-index: 1001;
display: flex;
height: 2rem;
justify-content: space-between;
align-items: center;
}
.dot-element {
height: 2rem;
width: 2rem;
border-radius: 1rem;
background-color: aquamarine;
opacity: 0.5;
transition: background-color 0.3s ease-in-out;
}
.active-dot {
background-color: red;
}
document.addEventListener('DOMContentLoaded', () => {
// CHANGE ONLY THIS
const SLIDE_TIME = 500; //ms
// --------------------------
// Buttons
const backButton = document.querySelector('.wbn-slider-back-btn');
const forwardButton = document.querySelector('.wbn-slider-next-btn');
// Select all slides and convert node to array for easy handling
// const allSlides = Array.from(document.querySelectorAll('.wbn-slide'));
const allSlides = [...document.querySelectorAll('.wbn-slide')];
// create progress dots
const dotsContainer = document.getElementById('dots-container');
allSlides.forEach(() => {
const dotElement = document.createElement('div');
dotElement.classList.add('dot-element');
dotsContainer.appendChild(dotElement);
});
const allDots = document.querySelectorAll('.dot-element');
// Helpers for active and newly active slides
let active;
const getActive = () => {
return document.querySelector('.active');
}
const getCurrentActiveIndex = () => {
return allSlides.indexOf(active);
}
let newActive = null;
const getNewActive = () => {
const activeSlideIndex = getCurrentActiveIndex();
return allSlides[(activeSlideIndex - 1 + allSlides.length) % allSlides.length];
}
const getCurrentNewActiveIndex = () => {
return allSlides.indexOf(newActive);
}
// Helpers to disable the arrows
let clickable = true;
function initSlider() {
active = getActive();
allSlides.forEach((slide) => {
// Set the CSS transition on the slides to the value we specified in SLIDE_TIME above
slide.setAttribute(
'style',
`transition: transform ${SLIDE_TIME}ms ease;
animation-duration: ${SLIDE_TIME}ms`,
);
// Add css transitions
slide.addEventListener('transitionstart', _e => {
allDots[getCurrentActiveIndex()].classList.remove('active-dot');
allDots[getCurrentNewActiveIndex()].classList.add('active-dot');
});
slide.addEventListener('transitionend', _e => {
// Check for the old active transition and if clickable is false
// to not trigger it more than once
if (slide === active && !clickable) {
clickable = true;
// Remove all CSS animation classes on old active
active.className = 'wbn-slide';
}
});
});
// Fist launch of the slider
if (allDots) {
allDots[getCurrentActiveIndex()].classList.add('active-dot');
}
}
function changeSlide(forward) {
if (clickable) {
clickable = false;
active = getActive();
const activeSlideIndex = getCurrentActiveIndex();
if (forward) {
newActive = allSlides[(activeSlideIndex + 1) % allSlides.length];
active.classList.add('slideOutLeft');
newActive.classList.add('slideInRight', 'active');
} else {
newActive = getNewActive();
active.classList.add('slideOutRight');
newActive.classList.add('slideInLeft', 'active');
}
}
}
//Event listeners
forwardButton.addEventListener('click', () => {
changeSlide(true);
});
backButton.addEventListener('click', () => {
changeSlide(false);
});
// Init the slider
initSlider();
});
@GGrassiant
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment