multiple sliders in one page website with javascript - javascript

I have to multiple sliders in my website. this code not work in my page for 3 sliders in one page.
but worked in one slider in one page. please help me do I it?
I need that this sliders worked in one page in my website. This sliders have to work into the accordion hover in one page.
The problem is that when I put all the slides, they all come together in one accordion.
In general, the main problem is that three sliders on one page do not work with this code
const slider = function () {
// const this_slider = this;
const slides = document.querySelectorAll('.slide');
const btnLeft = document.querySelector('.slider__btn--left');
const btnRight = document.querySelector('.slider__btn--right');
const dotContainer = document.querySelector('.dots');
let curSlide = 0;
const maxSlide = slides.length;
// Functions
const createDots = function () {
slides.forEach(function (_, i) {
dotContainer.insertAdjacentHTML(
'beforeend',
`<button class="dots__dot" data-slide="${i}"></button>`
);
});
};
const activateDot = function (slide) {
document
.querySelectorAll('.dots__dot')
.forEach(dot => dot.classList.remove('dots__dot--active'));
document
.querySelector(`.dots__dot[data-slide="${slide}"]`)
.classList.add('dots__dot--active');
};
const goToSlide = function (slide) {
slides.forEach(
(s, i) => (s.style.transform = `translateX(${100 * (i - slide)}%)`)
);
};
// Next slide
const nextSlide = function () {
if (curSlide === maxSlide - 1) {
curSlide = 0;
} else {
curSlide++;
}
goToSlide(curSlide);
activateDot(curSlide);
};
const prevSlide = function () {
if (curSlide === 0) {
curSlide = maxSlide - 1;
} else {
curSlide--;
}
goToSlide(curSlide);
activateDot(curSlide);
};
const init = function () {
goToSlide(0);
createDots();
activateDot(0);
};
init();
// Event handlers
btnRight.addEventListener('click', nextSlide);
btnLeft.addEventListener('click', prevSlide);
document.addEventListener('keydown', function (e) {
if (e.key === 'ArrowLeft') prevSlide();
e.key === 'ArrowRight' && nextSlide();
});
dotContainer.addEventListener('click', function (e) {
if (e.target.classList.contains('dots__dot')) {
const { slide } = e.target.dataset;
goToSlide(slide);
activateDot(slide);
}
});
};
slider();
/* SLIDER */
.slider {
max-width: 100rem;
height: 50rem;
margin: 0 auto;
position: relative;
/* IN THE END */
overflow: hidden;
}
.slide {
position: absolute;
top: 0;
width: 100%;
height: 50rem;
display: flex;
align-items: center;
justify-content: center;
/* THIS creates the animation! */
transition: transform 1s;
}
.slide > img {
/* Only for images that have different size than slide */
width: 100%;
height: 100%;
object-fit: cover;
}
.slider__btn {
position: absolute;
top: 50%;
z-index: 10;
border: none;
background-color: inherit;
/* background: rgba(255, 255, 255, 0.7); */
font-family: inherit;
color: white;
border-radius: 50%;
height: 5.5rem;
width: 5.5rem;
font-size: 3.25rem;
cursor: pointer;
}
.slider__btn--left {
left: 6%;
transform: translate(-50%, -50%);
}
.slider__btn--right {
right: 6%;
transform: translate(50%, -50%);
}
.dots {
position: absolute;
bottom: 5%;
left: 50%;
transform: translateX(-50%);
display: flex;
}
.dots__dot {
border: none;
background-color: #b9b9b9;
opacity: 0.7;
height: 1rem;
width: 1rem;
border-radius: 50%;
margin-right: 1.75rem;
cursor: pointer;
transition: all 0.5s;
/* Only necessary when overlying images */
/* box-shadow: 0 0.6rem 1.5rem rgba(0, 0, 0, 0.7); */
}
.dots__dot:last-child {
margin: 0;
}
.dots__dot--active {
/* background-color: #fff; */
background-color: blue;
opacity: 1;
}
.slideshow-container {
max-width: 1000px;
position: relative;
margin: auto;
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -22px;
color: white;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
}
/* Position the "next button" to the right */
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
/* On hover, add a grey background color */
.prev:hover,
.next:hover {
background-color: #f1f1f1;
color: black;
}
<div class="slider">
<div class="slide">
<img src="img/img-1.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-2.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-3.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-4.jpg" alt="">
</div>
<button class="slider__btn slider__btn--left">❮</button>
<button class="slider__btn slider__btn--right">❯</button>
<div class="dots"></div>
</div>

I have modified your html, css and script for demo.
html - added two more sliders and separated them.
css - added button colors for visibility
javascript - you can see it.
// We have to declare the function for all the sliders
// get all slider from document.
const slideContainer = document.querySelectorAll('.slider');
// lets put your function to every one of them
for(let i = 0; i < slideContainer.length; i++){
const slider = function () {
// const this_slider = this;
const slides = slideContainer[i].querySelectorAll('.slide'); // Your code was : const slides = document.querySelectorAll('.slide'); don't search the entire document, only search the slider
const btnLeft = slideContainer[i].querySelector('.slider__btn--left');
const btnRight = slideContainer[i].querySelector('.slider__btn--right');
const dotContainer = slideContainer[i].querySelector('.dots');
let curSlide = 0;
const maxSlide = slides.length;
// Functions
const createDots = function () {
slides.forEach(function (_, i) {
dotContainer.insertAdjacentHTML(
'beforeend',
`<button class="dots__dot" data-slide="${i}"></button>`
);
});
};
const activateDot = function (slide) {
slideContainer[i]
.querySelectorAll('.dots__dot')
.forEach(dot => dot.classList.remove('dots__dot--active'));
slideContainer[i]
.querySelector(`.dots__dot[data-slide="${slide}"]`)
.classList.add('dots__dot--active');
};
const goToSlide = function (slide) {
slides.forEach(
(s, i) => (s.style.transform = `translateX(${100 * (i - slide)}%)`)
);
};
// Next slide
const nextSlide = function () {
if (curSlide === maxSlide - 1) {
curSlide = 0;
} else {
curSlide++;
}
goToSlide(curSlide);
activateDot(curSlide);
};
const prevSlide = function () {
if (curSlide === 0) {
curSlide = maxSlide - 1;
} else {
curSlide--;
}
goToSlide(curSlide);
activateDot(curSlide);
};
const init = function () {
goToSlide(0);
createDots();
activateDot(0);
};
init();
// Event handlers
btnRight.addEventListener('click', nextSlide);
btnLeft.addEventListener('click', prevSlide);
document.addEventListener('keydown', function (e) {
if (e.key === 'ArrowLeft') prevSlide();
e.key === 'ArrowRight' && nextSlide();
});
dotContainer.addEventListener('click', function (e) {
if (e.target.classList.contains('dots__dot')) {
const { slide } = e.target.dataset;
goToSlide(slide);
activateDot(slide);
}
});
};
slider();
}
/* SLIDER */
.slider {
max-width: 100rem;
height: 50rem;
margin: 0 auto;
position: relative;
/* IN THE END */
overflow: hidden;
}
.slide {
position: absolute;
top: 0;
width: 100%;
height: 50rem;
display: flex;
align-items: center;
justify-content: center;
/* THIS creates the animation! */
transition: transform 1s;
}
.slide > img {
/* Only for images that have different size than slide */
width: 100%;
height: 100%;
object-fit: cover;
}
.slider__btn {
position: absolute;
top: 50%;
z-index: 10;
border: none;
background-color: black; // your was "inherit" . changed this for my visibility.
/* background: rgba(255, 255, 255, 0.7); */
font-family: inherit;
color: white;
border-radius: 50%;
height: 5.5rem;
width: 5.5rem;
font-size: 3.25rem;
cursor: pointer;
}
.slider__btn--left {
left: 6%;
transform: translate(-50%, -50%);
}
.slider__btn--right {
right: 6%;
transform: translate(50%, -50%);
}
.dots {
position: absolute;
bottom: 5%;
left: 50%;
transform: translateX(-50%);
display: flex;
}
.dots__dot {
border: none;
background-color: #b9b9b9;
opacity: 0.7;
height: 1rem;
width: 1rem;
border-radius: 50%;
margin-right: 1.75rem;
cursor: pointer;
transition: all 0.5s;
/* Only necessary when overlying images */
/* box-shadow: 0 0.6rem 1.5rem rgba(0, 0, 0, 0.7); */
}
.dots__dot:last-child {
margin: 0;
}
.dots__dot--active {
/* background-color: #fff; */
background-color: blue;
opacity: 1;
}
.slideshow-container {
max-width: 1000px;
position: relative;
margin: auto;
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -22px;
color: white;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
}
/* Position the "next button" to the right */
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
/* On hover, add a grey background color */
.prev:hover,
.next:hover {
background-color: #f1f1f1;
color: black;
}
<div class="slider">
<div class="slide">
<img src="img/img-1.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-2.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-3.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-4.jpg" alt="">
</div>
<button class="slider__btn slider__btn--left">❮</button>
<button class="slider__btn slider__btn--right">❯</button>
<div class="dots"></div>
</div>
<hr> <!-- This to separate the slider (optional)-->
<div class="slider">
<div class="slide">
<img src="img/img-1.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-2.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-3.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-4.jpg" alt="">
</div>
<button class="slider__btn slider__btn--left">❮</button>
<button class="slider__btn slider__btn--right">❯</button>
<div class="dots"></div>
</div>
<hr> <!-- This to separate the slider (optional)-->
<div class="slider">
<div class="slide">
<img src="img/img-1.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-2.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-3.jpg" alt="">
</div>
<div class="slide">
<img src="img/img-4.jpg" alt="">
</div>
<button class="slider__btn slider__btn--left">❮</button>
<button class="slider__btn slider__btn--right">❯</button>
<div class="dots"></div>
</div>

Related

Is there a way to make a CSS animation occur again on the click of another DIV?

Basically, I am trying to create an animation for CSS to fade into a slideshow of pictures on the click of a button (flute DIV top left). On the first click of the DIV the animation does play, but any other click after that does not load the animation (it does not fade). Is there a way to replay the animation once it is called for again (flute DIV clicked again)? Also don't mind the DIV slide's random placement still creating them lol. Here is my current code:
*Notice how the animation for the slideshow plays the first time, but any other time after it does not.
let slideIndex = 1;
//showSlides(slideIndex);
// Next/previous controls n = number selected in arrows
function plusSlides(n) {
showSlides(slideIndex += n);
}
// Thumbnail image controls
function currentSlide(nu) {
showSlides(slideIndex = nu);
}
function hide(newScale){
//newScale
var x = document.getElementById("x"),
image1 = document.getElementById("image1"),
image2 = document.getElementById("image2"),
image3 = document.getElementById("image3"),
imagew = document.getElementById("imagew")
contentw = document.getElementById("contentw");
document.getElementById('image1').style.WebkitTransition = 'opacity 1s';
contentw.style.zIndex = "111111111111111111111112";
imagew.style.zIndex = "111111111111111111111112";
image1.style.transform = `scale(${newScale})`;
image2.style.transform = `scale(${newScale})`;
image3.style.transform = `scale(${newScale})`;
x.style.transform = `scale(${newScale})`;
}
function changeScale(newScale){
var div1 = document.getElementById("dot1");
var div2 = document.getElementById("dot2");
var div3 = document.getElementById("dot3");
var x = document.getElementById("x");
var image1 = document.getElementById("image1"),
image2 = document.getElementById("image2"),
image3 = document.getElementById("image3");
image1.style.transform = `scale(${newScale})`;
image2.style.transform = `scale(${newScale})`;
image3.style.transform = `scale(${newScale})`;
var prev = document.getElementById("p");
var next = document.getElementById("n");
// div1.style.transform = div1.style.transform.replace(/scale\([0-9|\.]*\)/, 'scale(' + newScale + ')');
// div2.style.transform = div2.style.transform.replace(/scale\([0-9|\.]*\)/, 'scale(' + newScale + ')');
// div3.style.transform = div3.style.transform.replace(/scale\([0-9|\.]*\)/, 'scale(' + newScale + ')');
div1.style.transform = `scale(${newScale})`;
div2.style.transform = `scale(${newScale})`;
div3.style.transform = `scale(${newScale})`;
div1.style.zIndex = "99999999999999";
contentw.style.zIndex = "-1";
imagew.style.zIndex = "-1";
prev.style.transform = `scale(${newScale})`;
next.style.transform = `scale(${newScale})`;
x.style.transform = `scale(${newScale})`;
}
function showSlides(n) {
//makes i variable, gets slides and dots on slideshow
let i;
let slides = document.getElementsByClassName("mySlides");
let dots = document.getElementsByClassName("dot");
//n = number inputted/selected
if (n > slides.length) {slideIndex = 1}
if (n < 1) {slideIndex = slides.length}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " active";
}
.h2{
font-family: 'Roboto', serif;
}
body {
background-color: #000000;
}
.wrapper {
display: flex;
flex-direction: column;
width: 400px;
justify-content: center;
align-items: center;
border-radius: 3rem;
/*box-shadow: 0.6rem 0.6rem 1.9rem #525c5c, -0.5em -0.5em 1em #ffffff;*/
z-index: 100;
transition-duration: 0.1s; /* ADD */
}
.wrapper:hover {
text-shadow: 5px 5px 4px lightgray;
cursor: pointer;
transition-duration: 0.2s;
}
.wrapper .image {
overflow: hidden; /* ADD */
border-radius: 1rem; /* ADD */
}
.wrapper .image img {
width: 100%;
object-fit: cover;
border-radius: 1rem; /*REMOVE */
cursor: pointer;
transition: transform 0.5s; /* ADD */
}
.wrapper:hover img { /* change scale? */
transform: scale(1.5);
}
.wrapper .infocontent {
display: flex;
justify-content: center;
align-items: center;
text-shadow: .5px 2px 10px rgba(214, 205, 205, 0.616);
font-weight: bold;
font-family: Consolas;
letter-spacing: 2px;
color: #441d9e;
cursor: pointer;
}
* {box-sizing:border-box}
/* Slideshow container */
.slideshow-container {
max-width: 1000px;
position: relative;
margin: auto;
}
/* Hide the images by default */
.mySlides {
/* display: none;
width: 100%;
height: 100%; */
width: 100%;
height: 100%;
position: fixed;
top: 0px;
left: 0px;
z-index: 1111111;
display: none;
}
#x{
cursor: pointer;
transform: scale(0);
position: absolute;
right: -25vh;
top: -56vh;
font-size: 4vh;
background:rgba(39, 58, 29, 0.596);
border-radius: 50%;
display: flex; /* or inline-flex */
align-items: center;
justify-content: center; width:40px;
height:40px;
z-index: 1111111;
}
#x:hover{
background:rgba(86, 163, 44, 0.596)
}
#x:active{
background:rgba(189, 1, 1, 0.596);
/* border:rgba(86, 163, 44, 0.596) 100px; */
border: 100px;
/*border-width: 105px;*/
border:1px solid red;
}
#p, #n{
transform: scale(0);
}
/* Next & previous buttons */
.prev, .next {
z-index: 1111111;
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
margin-top: -22px;
padding: 16px;
color: white;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
}
/* Position the "next button" to the right */
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
/* On hover, add a black background color with a little bit see-through */
.prev:hover{
background-color: rgba(53, 49, 49, 0.37);
}
.next:hover {
background-color: rgba(53, 49, 49, 0.37);
}
/* Caption text */
.text {
color: #f2f2f2;
font-size: 15px;
padding: 8px 12px;
position: absolute;
bottom: 8px;
width: 100%;
text-align: center;
}
/* Number text (1/3 etc) */
.numbertext {
color: #f2f2f2;
font-size: 12px;
padding: 8px 12px;
position: absolute;
top: 0;
}
/* The dots/bullets/indicators */
.dot {
top: 90vh;
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 2px;
background-color: rgb(255, 255, 255);
border-radius: 50%;
display: inline-block;
transition: background-color 0.3s ease, box-shadow 0.4s ease;
}
#dot1{
position:fixed;
left: 103vh;
z-index: 1111111;
transform: scale(0);
}
#dot2{
position:fixed;
left: 107vh;
z-index: 1111111;
transform: scale(0);
}
#dot3{
position:fixed;
left: 111vh;
z-index: 1111111;
transform: scale(0);
}
.dot:hover {
box-shadow: 0.3rem 0.3rem 5rem #525c5c, 0em 0em 0.9em #ffffff98;
background-color: #807b7b;
}
.active{
background-color: #272727;
box-shadow: 0.3rem 0.3rem 5rem #525c5c, 0em 0em 0.45em #ffffff;
}
/* .hide{
} */
/* Fading animation */
.fade {
animation-name: fade;
animation-duration: 1.5s;
/* animation-iteration-count: infinite; */
}
#keyframes fade {
from {opacity: .4}
to {opacity: 1}
}
#keyframes fadeOut{
from {opacity: 1}
to {opacity: 0}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<title>Flute</title>
<!-- <link rel = "icon" href = "images/apple.png" type = "image/x-icon"> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/addons/p5.dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/addons/p5.sound.min.js"></script>
<script src="p5.play.js"></script>
<script src="const.js"></script>
<h1 class = "h2">Flute</h1>
<link rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto">
<div class="wrapper" >
<div class="image" id = "imagew">
<img src="https://static01.nyt.com/images/2021/02/06/lens/06xp-flute1/06xp-flute1-jumbo-v2.jpg?quality=75&auto=webp"
title = "Golden Flute Background (possibly article?)" onclick = "currentSlide(1); changeScale(1); ">
</div>
<div class="infocontent" id = "contentw">
<h3><strong>Golden Flute</strong></h3>
</div>
</div>
<!-- Slideshow container -->
<div class="slideshow-container" >
<!-- Full-width images with number and caption text -->
<div class="mySlides fade" >
<div class="numbertext" id = "caption1">1 / 3</div>
<img id ="image1" src="https://static01.nyt.com/images/2021/02/06/lens/06xp-flute1/06xp-flute1-jumbo-v2.jpg?quality=75&auto=webp" style="width:100%">
<div class="text" id = "text1">Caption Text</div>
</div>
<div class="mySlides fade">
<div class="numbertext" id = "caption2">2 / 3</div>
<img id ="image2" src="https://images.ctfassets.net/cnu0m8re1exe/1VrluBtdwQy4uTrLEhqZGM/182f5254239d5a93dc442793a633acbd/Crystal_Flute.jpg?fm=jpg&fl=progressive&w=660&h=433&fit=fill" style="width:100%">
<div class="text" id = "textq">Caption Two</div>
</div>
<div class="mySlides fade">
<div class="numbertext" id = "caption2">3 / 3</div>
<img id ="image3" src="https://ventured.com/wp-content/uploads/2020/10/William-Kincaids-Verne-Q.-Powell-Flute-768x576.jpg" style="width:100%">
<div class="text" id = "text3">Caption Three</div>
</div>
<!-- Next and previous buttons -->
<a class="prev" id = "x" onclick="hide(0);">✕</a>
<!-- onclick="plusSlides(-1)" -->
<a class="prev" id = "p" onclick="plusSlides(-1)">❮</a>
<a class="next" id = "n" onclick="plusSlides(1)">❯</a>
</div>
<br>
<!-- The dots/circles -->
<div style="text-align:center" >
<span class="dot" onclick="currentSlide(1)" id = "dot1"></span>
<span class="dot" onclick="currentSlide(2)" id = "dot2"></span>
<span class="dot" onclick="currentSlide(3)" id = "dot3"></span>
</div>

Removing onScroll event when menu is clicked

When menu is clicked I want it to be fixed not scrollable.
How can I remove the event listener on scroll so the menu is staying fixed and scrolling up and down? JavaScript is not my strong skill and if someone with more experience can help me out, it would be greatly appreciated. Thank you
const header = document.querySelector(".hiding-header");
const triggerMenu = document.querySelector(".page-header .trigger-menu");
const nav = document.querySelector(".page-header nav");
const menu = document.querySelector(".page-header .menu");
const scrollUp = "scroll-up";
const scrollDown = "scroll-down";
let lastScroll = 0;
triggerMenu.addEventListener("click", () => {
header.classList.toggle("menu-open");
});
window.addEventListener("scroll", () => {
const currentScroll = window.pageYOffset;
if (currentScroll <= 0) {
header.classList.remove(scrollUp);
return;
}
if (currentScroll > lastScroll && !header.classList.contains(scrollDown)) {
// down
header.classList.remove(scrollUp);
header.classList.add(scrollDown);
} else if (
currentScroll < lastScroll &&
header.classList.contains(scrollDown)
) {
// up
header.classList.remove(scrollDown);
header.classList.add(scrollUp);
}
lastScroll = currentScroll;
});
:root {
--white: #fff;
--black: #221f1f;
--lightpurple: #9e91f2;
--darkgray: #1e1f26;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
button {
background: transparent;
border: none;
cursor: pointer;
outline: none;
}
ul {
list-style: none;
}
a {
text-decoration: none;
color: inherit;
}
body {
position: relative;
font: 16px/1.5 sans-serif;
color: var(--white);
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
}
/* MAIN RULES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.trigger-menu-wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
display: flex;
justify-content: end;
padding: 20px;
z-index: 2;
background: var(--lightpurple);
transition: transform 0.4s;
}
.page-header .trigger-menu {
display: flex;
align-items: center;
font-size: 1.3rem;
color: var(--white);
letter-spacing: 0.2em;
}
.page-header .trigger-menu svg {
fill: var(--white);
margin-right: 8px;
transition: transform 0.3s;
}
.page-header .menu {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: none;
text-align: center;
padding: 15vh 0 5vh;
overflow: auto;
z-index: 1;
background: var(--lightpurple);
}
.page-header .menu a {
font-size: 3rem;
}
.page-header .sub-menu a {
font-size: 1.5rem;
}
.lottie-wrapper {
position: fixed;
bottom: 50px;
right: 25px;
z-index: 1;
padding: 5px;
border-radius: 5px;
}
.page-main section {
position: relative;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
height: 100vh;
}
.page-main section::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.25);
}
/* BODY CLASSES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.menu-open {
overflow: hidden;
}
.menu-open .trigger-menu-wrapper {
background: transparent;
position: fixed;
}
.menu-open .page-header .menu {
display: block;
}
.menu-open .page-header svg {
transform: rotate(45deg);
}
.menu-open-with-lottie .page-header .menu {
padding: 5vh 0;
}
.scroll-down .trigger-menu-wrapper {
transform: translate3d(0, -100%, 0);
}
.scroll-down .lottie-wrapper {
background: var(--darkgray);
}
.scroll-up .trigger-menu-wrapper {
transform: none;
}
.scroll-up:not(.menu-open) .trigger-menu-wrapper {
background: var(--lightpurple);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.35);
}
/* FOOTER
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.page-footer {
position: fixed;
right: 25px;
bottom: 10px;
display: flex;
align-items: center;
font-size: 1rem;
padding: 5px;
border-radius: 5px;
background: var(--darkgray);
}
.page-footer a {
display: flex;
margin-left: 4px;
}
<script src="https://unpkg.com/#lottiefiles/lottie-player#latest/dist/lottie-player.js"></script>
<header class="hiding-header">
<nav class="page-header">
<div class="trigger-menu-wrapper">
<button class="trigger-menu">
<svg width="12" height="12" viewBox="0 0 24 24">
<path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z" />
</svg>
<span>MENU</span>
</button>
</div>
<ul class="menu">
<li>
About
<ul class="sub-menu">
<li>
History
</li>
<li>
President
</li>
<li>
Team
</li>
<li>
Process
</li>
<li>
Clients
</li>
</ul>
</li>
</ul>
</nav>
</header>
<!-- <a href="" role="button" aria-label="Toggle menu" class="lottie-wrapper">
<lottie-player src="https://assets10.lottiefiles.com/datafiles/9gIwZ2uiiKglyb0/data.json" style="width: 60px; height: 60px;"></lottie-player>
</a> -->
<main class="page-main">
<section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/freedom.jpg);"></section>
<section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/travel.jpg);"></section>
<section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/holidays.jpg);"></section>
</main>
<footer class="page-footer">
<!-- <span>made by </span>
<a href="https://georgemartsoukos.com/" target="_blank">
<img width="24" height="24" src="https://assets.codepen.io/162656/george-martsoukos-small-logo.svg" alt="George Martsoukos logo">
</a> -->
</footer>
You can use
removeEventListener(type, listener);
although you may need to make your scroll event a function rather than an anonymous function
const header = document.querySelector(".hiding-header");
const triggerMenu = document.querySelector(".page-header .trigger-menu");
const nav = document.querySelector(".page-header nav");
const menu = document.querySelector(".page-header .menu");
const scrollUp = "scroll-up";
const scrollDown = "scroll-down";
let lastScroll = 0;
triggerMenu.addEventListener("click", () => {
header.classList.toggle("menu-open");
window.removeEventListener("scroll", handleScroll)
});
window.addEventListener("scroll", handleScroll);
function handleScroll() {
const currentScroll = window.pageYOffset;
if (currentScroll <= 0) {
header.classList.remove(scrollUp);
return;
}
if (currentScroll > lastScroll && !header.classList.contains(scrollDown)) {
// down
header.classList.remove(scrollUp);
header.classList.add(scrollDown);
} else if (
currentScroll < lastScroll &&
header.classList.contains(scrollDown)
) {
// up
header.classList.remove(scrollDown);
header.classList.add(scrollUp);
}
lastScroll = currentScroll;
}
To add to #jay's point you cannot call removeEventListener without the original listener function. If you call addEventListener with an anonymous function, you cannot easily remove it, note you could forcibly remove all listeners for DOM elements as mentioned here but it's ugly and not ideal.
Good ✅
const handleScroll = () => {
console.log('scrolling...');
};
document.addEventListener('scroll', handleScroll);
document.removeEventListener('scroll', handleScroll);
Bad ❌
document.addEventListener('scroll', () => {
console.log('scrolling...');
})
document.removeEventListener('scroll', () => {
console.log('scrolling...');
}) // does not throw error but fails to remove listener
Note: It can be a little deceiving calling removeEventListener without getting an error thinking it worked but this is not the case. Removal is attempted but not certain if no matching listeners are found.
More considerations
Using the original listener is one part put the removal of listeners depends on the options as well, see docs for more details.
Dev Tools helper
You can always use the dev tools Event Listeners tab to inspect an element or document.body and see all active listeners to know for sure when listeners are removed.
Solution to disable scroll when menu open
Yeah your question was not really about the scroll listener but how to disable the scroll, as you have found out the listener does not stop the scroll just stops listening.
For what you are looking for there are few options the vary in complexity, but the easiest fastest way to make it work is just to add a class to turn scrolling off on the scrolling element.
In you case you are scrolling the document.body, so we need to add a class to the body when the menu is clicked and remove it when it's clicked again to close.
triggerMenu.addEventListener("click", () => {
header.classList.toggle("menu-open");
document.body.classList.toggle('disable-scroll'); // <-- add this line
});
body.disable-scroll {
overflow: hidden; // prevents scrolling on the body
}
See working demo below...
const header = document.querySelector(".hiding-header");
const triggerMenu = document.querySelector(".page-header .trigger-menu");
const nav = document.querySelector(".page-header nav");
const menu = document.querySelector(".page-header .menu");
const scrollUp = "scroll-up";
const scrollDown = "scroll-down";
let lastScroll = 0;
triggerMenu.addEventListener("click", () => {
header.classList.toggle("menu-open");
document.body.classList.toggle('disable-scroll');
});
window.addEventListener("scroll", handleScroll);
function handleScroll(e) {
const currentScroll = window.pageYOffset;
if (currentScroll <= 0) {
header.classList.remove(scrollUp);
return;
}
if (currentScroll > lastScroll && !header.classList.contains(scrollDown)) {
// down
header.classList.remove(scrollUp);
header.classList.add(scrollDown);
} else if (
currentScroll < lastScroll &&
header.classList.contains(scrollDown)
) {
// up
header.classList.remove(scrollDown);
header.classList.add(scrollUp);
}
lastScroll = currentScroll;
}
:root {
--white: #fff;
--black: #221f1f;
--lightpurple: #9e91f2;
--darkgray: #1e1f26;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
button {
background: transparent;
border: none;
cursor: pointer;
outline: none;
}
ul {
list-style: none;
}
a {
text-decoration: none;
color: inherit;
}
body {
position: relative;
font: 16px/1.5 sans-serif;
color: var(--white);
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
body.disable-scroll {
overflow: hidden;
}
/* MAIN RULES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.trigger-menu-wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
display: flex;
justify-content: end;
padding: 20px;
z-index: 2;
background: var(--lightpurple);
transition: transform 0.4s;
}
.page-header .trigger-menu {
display: flex;
align-items: center;
font-size: 1.3rem;
color: var(--white);
letter-spacing: 0.2em;
}
.page-header .trigger-menu svg {
fill: var(--white);
margin-right: 8px;
transition: transform 0.3s;
}
.page-header .menu {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: none;
text-align: center;
padding: 15vh 0 5vh;
overflow: auto;
z-index: 1;
background: var(--lightpurple);
}
.page-header .menu a {
font-size: 3rem;
}
.page-header .sub-menu a {
font-size: 1.5rem;
}
.lottie-wrapper {
position: fixed;
bottom: 50px;
right: 25px;
z-index: 1;
padding: 5px;
border-radius: 5px;
}
.page-main section {
position: relative;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
height: 100vh;
}
.page-main section::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.25);
}
/* BODY CLASSES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.menu-open {
overflow: hidden;
}
.menu-open .trigger-menu-wrapper {
background: transparent;
position: fixed;
}
.menu-open .page-header .menu {
display: block;
}
.menu-open .page-header svg {
transform: rotate(45deg);
}
.menu-open-with-lottie .page-header .menu {
padding: 5vh 0;
}
.scroll-down .trigger-menu-wrapper {
transform: translate3d(0, -100%, 0);
}
.scroll-down .lottie-wrapper {
background: var(--darkgray);
}
.scroll-up .trigger-menu-wrapper {
transform: none;
}
.scroll-up:not(.menu-open) .trigger-menu-wrapper {
background: var(--lightpurple);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.35);
}
/* FOOTER
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.page-footer {
position: fixed;
right: 25px;
bottom: 10px;
display: flex;
align-items: center;
font-size: 1rem;
padding: 5px;
border-radius: 5px;
background: var(--darkgray);
}
.page-footer a {
display: flex;
margin-left: 4px;
}
<script src="https://unpkg.com/#lottiefiles/lottie-player#latest/dist/lottie-player.js"></script>
<header class="hiding-header">
<nav class="page-header">
<div class="trigger-menu-wrapper">
<button class="trigger-menu">
<svg width="12" height="12" viewBox="0 0 24 24">
<path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z" />
</svg>
<span>MENU</span>
</button>
</div>
<ul class="menu">
<li>
About
<ul class="sub-menu">
<li>
History
</li>
<li>
President
</li>
<li>
Team
</li>
<li>
Process
</li>
<li>
Clients
</li>
</ul>
</li>
</ul>
</nav>
</header>
<!-- <a href="" role="button" aria-label="Toggle menu" class="lottie-wrapper">
<lottie-player src="https://assets10.lottiefiles.com/datafiles/9gIwZ2uiiKglyb0/data.json" style="width: 60px; height: 60px;"></lottie-player>
</a> -->
<main class="page-main">
<section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/freedom.jpg);"></section>
<section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/travel.jpg);"></section>
<section style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/162656/holidays.jpg);"></section>
</main>
<footer class="page-footer">
<!-- <span>made by </span>
<a href="https://georgemartsoukos.com/" target="_blank">
<img width="24" height="24" src="https://assets.codepen.io/162656/george-martsoukos-small-logo.svg" alt="George Martsoukos logo">
</a> -->
</footer>
Note: The biggest issues with approach is the scroll bars/width of the page can snap back and forth creating a jarring UI twitch. The second is that it clears the user scroll height, if they scroll to the bottom then open the menu and close it the scroll would jump back to the top. Since you hide the menu unless the user is at the top this doesn't matter in your case. The other issue is not noticeable in this case.

Slideshow with different amount of images per slide

I'm trying to do a slideshow. A normal slideshow has one image per slide, but in my case every slide has different amount of images.
Here is an example of 2 slides:
First Slide
Second Slide
I've working fine with one image, but can't put with more than that per page.
let currentSlide = 0;
const slides = document.querySelectorAll(".slide")
const dots = document.querySelectorAll('.dot')
const init = (n) => {
slides.forEach((slide, index) => {
slide.style.display = "none"
dots.forEach((dot, index) => {
dot.classList.remove("active")
})
})
slides[n].style.display = "block"
dots[n].classList.add("active")
}
document.addEventListener("DOMContentLoaded", init(currentSlide))
const next = () => {
currentSlide >= slides.length - 1 ? currentSlide = 0 : currentSlide++
init(currentSlide)
}
const prev = () => {
currentSlide <= 0 ? currentSlide = slides.length - 1 : currentSlide--
init(currentSlide)
}
document.querySelector(".next").addEventListener('click', next)
document.querySelector(".prev").addEventListener('click', prev)
setInterval(() => {
next()
}, 5000);
dots.forEach((dot, i) => {
dot.addEventListener("click", () => {
console.log(currentSlide)
init(i)
currentSlide = i
})
})
.slide-container .prev,
.slide-container .next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
margin-top: -22px;
padding: 16px;
color: white;
font-weight: bold;
font-size: 20px;
transition: all 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
}
.slide-container .prev:hover,
.slide-container .next:hover {
background-color: rgba(0, 0, 0, 0.8);
color: white;
}
.slide-container .prev {
left: 2px;
}
.slide-container .next {
right: 2px;
}
.dots-container {
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
}
.dots-container .dot {
cursor: pointer;
margin: 5px;
width: 20px;
height: 20px;
color: #333;
border-radius: 50%;
background-color: #dfd6ce;
}
.dots-container .dot.active {
border: 2px solid green;
}
* {
padding: 0;
border: 0;
box-sizing: border-box;
}
body {
height: 100%;
/* background-image: linear-gradient(to top, #accbee 0%, #e7f0fd 100%); */
}
body h1 {
text-align: center;
}
.slide-container {
display: flex;
justify-content: center;
align-items: center;
max-width: 1000px;
margin: auto;
position: relative;
}
.slide-container .slide {
display: none;
width: 100%;
}
.slide-container .slide.fade {
animation: fade 0.5s cubic-bezier(0.55, 0.085, 0.68, 0.53) both;
}
.slide-container .slide img {
width: 100%;
}
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Image Slider</title>
</head>
<body>
<h1>Image Slider</h1>
<div class="slide-container">
<div class="slide fade">
<img src='https://images.unsplash.com/photo-1590595978583-3967cf17d2ea?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ' alt=''>
</div>
<div class="slide fade">
<img src='https://images.unsplash.com/photo-1588807308097-fb6e5047df8c?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ' alt=''>
</div>
<div class="slide fade">
<img src='https://images.unsplash.com/photo-1589808710416-24cf7ac026f2?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ' alt=''>
</div>
<div class="slide fade">
<img src='https://images.unsplash.com/photo-1588796388882-a4d533c47e5e?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ' alt=''>
</div>
&#10094
&#10095
</div>
<div class="dots-container">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</body>
</html>
If anyone can help, it will help a lot.
Thanks
One way of getting more than one image per slide is to put several img elements in the slide and size them accordingly.
This snippet is just basic - put two imgs into the first slide and give them 45% width each (so they have room to be next to each other).
Depending on how general you need to be you will have to do some sort of calculation for each slide which calculates the relevant width for each image in it, possibly just 100/n% of the slide's width, but maybe more complex if your images are of different aspect ratios.
let currentSlide = 0;
const slides = document.querySelectorAll(".slide")
const dots = document.querySelectorAll('.dot')
const init = (n) => {
slides.forEach((slide, index) => {
slide.style.display = "none"
dots.forEach((dot, index) => {
dot.classList.remove("active")
})
})
slides[n].style.display = "block"
dots[n].classList.add("active")
}
document.addEventListener("DOMContentLoaded", init(currentSlide))
const next = () => {
currentSlide >= slides.length - 1 ? currentSlide = 0 : currentSlide++
init(currentSlide)
}
const prev = () => {
currentSlide <= 0 ? currentSlide = slides.length - 1 : currentSlide--
init(currentSlide)
}
document.querySelector(".next").addEventListener('click', next)
document.querySelector(".prev").addEventListener('click', prev)
setInterval(() => {
next()
}, 5000);
dots.forEach((dot, i) => {
dot.addEventListener("click", () => {
console.log(currentSlide)
init(i)
currentSlide = i
})
})
.slide-container .prev,
.slide-container .next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
margin-top: -22px;
padding: 16px;
color: white;
font-weight: bold;
font-size: 20px;
transition: all 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
}
.slide-container .prev:hover,
.slide-container .next:hover {
background-color: rgba(0, 0, 0, 0.8);
color: white;
}
.slide-container .prev {
left: 2px;
}
.slide-container .next {
right: 2px;
}
.dots-container {
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
}
.dots-container .dot {
cursor: pointer;
margin: 5px;
width: 20px;
height: 20px;
color: #333;
border-radius: 50%;
background-color: #dfd6ce;
}
.dots-container .dot.active {
border: 2px solid green;
}
* {
padding: 0;
border: 0;
box-sizing: border-box;
}
body {
height: 100%;
/* background-image: linear-gradient(to top, #accbee 0%, #e7f0fd 100%); */
}
body h1 {
text-align: center;
}
.slide-container {
display: flex;
justify-content: center;
align-items: center;
max-width: 1000px;
margin: auto;
position: relative;
}
.slide-container .slide {
display: none;
width: 100%;
}
.slide-container .slide.fade {
animation: fade 0.5s cubic-bezier(0.55, 0.085, 0.68, 0.53) both;
}
.slide-container .slide img {
width: 100%;
}
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Image Slider</title>
</head>
<body>
<h1>Image Slider</h1>
<div class="slide-container">
<div class="slide fade">
<img src='https://images.unsplash.com/photo-1590595978583-3967cf17d2ea?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ' alt='' style="width: 45%; height: auto;">
<img src='https://images.unsplash.com/photo-1588807308097-fb6e5047df8c?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ' alt='' style="width: 45%; height: auto;">
</div>
<div class="slide fade">
<img src='https://images.unsplash.com/photo-1588807308097-fb6e5047df8c?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ' alt=''>
</div>
<div class="slide fade">
<img src='https://images.unsplash.com/photo-1589808710416-24cf7ac026f2?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ' alt=''>
</div>
<div class="slide fade">
<img src='https://images.unsplash.com/photo-1588796388882-a4d533c47e5e?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ' alt=''>
</div>
&#10094
&#10095
</div>
<div class="dots-container">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</div>
</body>
</html>

Javascript: Carousel active dots and left-right buttons

I am beginner level javascript developer. I have decide to make carousel by using pure Javascript. I successfully manage to slide the carousel. I have decided to make active dots(also clickable), i want the dots background colour change when slide happen and left-right button. I have created the dots but I don't know how to implement the dots in my slide function as well left and right button. Here is my code:
Also please explain me the logic. Thank you
const images = document.getElementById('imgs');
const allImages = document.querySelectorAll('#imgs img');
const leftBtn = document.getElementById('left');
const rightBtn = document.getElementById('right');
let index = 0;
function run() {
const dot = [...document.getElementsByClassName('star')];
index++;
if (index > allImages.length - 1) {
index = 0
dot.forEach(i => i.classList.add('active'))
}
imgs.style.transform = `translateX(${-index * 500}px)`
}
const dot = allImages.forEach(i => {
const elem = document.createElement('div');
elem.classList.add('star');
document.body.appendChild(elem)
})
let x = setInterval(run, 2000);
images.onmouseover = () => {
clearInterval(x)
}
images.onmouseout = () => {
x = setInterval(run, 2000);
}
*{
box-sizing: border-box;
}
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.carousel {
overflow: hidden;
width: 500px;
height: 500px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, .3);
border-radius: 5px;
}
.image-container {
display: flex;
transition: transform 300ms linear;
transform: translateX(0);
}
img {
width:500px;
height: 500px;
object-fit: cover;
}
.star{
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 10px;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
background-color: #eeeeee;
}
.star.active{
background-color: red;
}
button{
cursor: pointer;
position: relative;
font-size: 18px;
transition: 0.6s ease;
user-select: none;
height: 50px;
width: 40px;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
top: calc(50% - 25px);
}
button:hover {
background-color: rgba(0,0,0,0.8);
};
button.left {
border-radius: 3px 0 0 3px;
right: 0;
}
button.left {
border-radius: 3px 0 0 3px;
left: 0;
}
<button id="left">❮</button>
<button id="right">❯</button>
<div class="carousel">
<div class="image-container" id="imgs" >
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/photo-1516026672322-bc52d61a55d5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/photo-1573081586928-127ecc7948b0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/flagged/photo-1572850005109-f4ac7529bf9f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
</div>
You were close to the result. In your run function, you just have to change the class of the current active dot and set the new one to active. I renamed your dot variable to dots for the sake of comprehension.
function run() {
const dots = [...document.getElementsByClassName('star')];
index++;
if (index > allImages.length - 1) {
index = 0
}
dots.forEach((dot, i) => {
if (dot.classList.contains('active')) dot.classList.remove('active');
if (i === index) dot.classList.add('active'));
}
imgs.style.transform = `translateX(${-index * 500}px)`
}

Image Carousel: Force Images to take up entire div (each image)

I need a way to force each image to fill the div no matter the size of the div. I thought this is what width: 100% was supposed to do but it's not working the way I expected it to.
Link to CodePen
const carousels = document.querySelectorAll('.image-carousel');
[].forEach.call(carousels, c => {
let next = document.querySelector('.next'),
prev = document.querySelector('.previous'),
bubblesContainer = document.querySelector('.bubbles'),
inner = document.querySelector('.inner'),
imgs = document.querySelectorAll('img'),
currentImageIndex = 0,
width = 100,
bubbles = [];
for (let i = 0; i < imgs.length; i++) {
let b = document.createElement('span');
b.classList.add('bubble');
bubblesContainer.append(b);
bubbles.push(b);
b.addEventListener('click', () => {
currentImageIndex = i;
switchImg();
});
}
function switchImg() {
inner.style.left = -width * currentImageIndex + '%';
bubbles.forEach(function (b, i) {
if (i === currentImageIndex) {
b.classList.add('active');
} else {
b.classList.remove('active');
}
});
}
next.addEventListener('click', () => {
currentImageIndex++;
if (currentImageIndex >= imgs.length) {
currentImageIndex = 0;
}
switchImg();
});
prev.addEventListener('click', () => {
currentImageIndex--;
if (currentImageIndex < 0) {
currentImageIndex = imgs.length - 1;
}
switchImg();
});
switchImg();
});
img {
height: 100%;
min-width: 100%;
}
.image-carousel {
width: 100%;
height: 50vh;
overflow: hidden;
position: relative;
}
.image-carousel .inner {
display: flex;
position: absolute;
left: 0;
transition: left 0.5s;
width: 100%;
height: 100%;
}
.image-carousel .bubbles {
display: flex;
justify-content: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
margin-bottom: 5px;
}
.image-carousel .bubbles .bubble {
margin: 0 1rem 0.5rem;
background: white;
border-radius: 100%;
width: 10px;
height: 10px;
display: inline-block;
opacity: 0.25;
transition: 0.1s;
cursor: pointer;
}
.image-carousel .bubbles .bubble:hover {
opacity: 0.65;
}
.image-carousel .bubbles .bubble.active {
opacity: 1;
}
.image-carousel .next::after, .image-carousel .previous::after {
content: '>';
position: absolute;
top: 50%;
right: 0;
background: white;
width: 1rem;
height: 3rem;
font-weight: bold;
transform: translatey(-50%);
line-height: 3rem;
box-sizing: border-box;
padding: 0 0.2rem;
cursor: pointer;
}
.image-carousel .previous::after {
left: 0;
content: '<';
}
<div class="container">
<div class="row">
<div class="col-12">
<div class="image-carousel">
<div class="inner">
<img class="carousel one" src="https://via.placeholder.com/100x100">
<img class="carousel two" src="https://via.placeholder.com/100x100">
<img class="carousel three" src="https://via.placeholder.com/100x100">
<img class="carousel three" src="https://via.placeholder.com/100x100">
</div>
<div class="bubbles"></div>
<div class="previous"><button><</button></div>
<div class="next"><button>></button></div>
</div>
</div>
</div>
</div>
You can try adding display:block; min-width: 100%; Min-width forces element to fill parents width.
The issue is that you've set the .inner element's display property to flex.
You can remove flex or add flex: 0 0 100% to your images like so:
.inner {
..
img {
flex: 0 0 100%;
}
}
flex: 0 0 100% is telling the element inside a flex container to not shrink, or expand, and take up 100% of its parent.

Categories

Resources