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)`
}
Related
I'm using HTML/CSS and vanilla JS. I'm trying to create a simple carousel. However, whenever I click the 'next' button, the following slides show up under the last one. I'm not sure why this is happening. Code snippets are below. Can someone explain why this is happening?
By the way, I have not optimized this page for media queries yet, so it might look a little weird on smaller screens.
const buttons = document.querySelectorAll("[data-carousel-btn]");
buttons.forEach((button) => {
button.addEventListener("click", () => {
const offset = button.dataset.carouselBtn === "next" ? 1 : -1;
const slidesContainer = button
.closest("[data-carousel]")
.querySelector("[data-carousel-slides");
const slides = slidesContainer.querySelectorAll("[data-carousel-slide]");
const activeSlide = slidesContainer.querySelector("[data-active]");
const activeSlideIndex = [...slides].indexOf(activeSlide);
const nextSlideIndex = activeSlideIndex + offset;
if (nextSlideIndex < 0) {
slides[slides.length + nextSlideIndex].dataset.active = true;
return delete activeSlide.dataset.active;
}
if (nextSlideIndex >= slides.length) {
slides[0].dataset.active = true;
return delete activeSlide.dataset.active;
}
slides[nextSlideIndex].dataset.active = true;
return delete activeSlide.dataset.active;
});
});
.carouselContainer {
width: 1000px;
height: 500px;
position: relative;
display: flex;
justify-content: center;
border-style: dashed;
border-color: #010043;
}
.carouselContainer>ul {
padding: 0;
margin: 0;
list-style: none;
}
.slide {
display: flex;
width: 400px;
height: 500px;
justify-content: center;
align-items: center;
inset: 0;
opacity: 0;
transition-property: opacity;
transition-duration: 200ms;
transition-timing-function: ease-in-out;
transition-delay: 200ms;
border-style: dashed;
border-color: var(--magenta6);
}
.slide[data-active] {
opacity: 1;
z-index: 1;
transition-delay: 0ms;
}
.slideContent {
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: column;
width: 300px;
height: 425px;
border-style: dashed;
border-color: #010043;
}
.slideContent .slideImg {
margin: 0;
width: 200px;
height: 200px;
border-radius: 100px;
z-index: 10px;
}
.slideContent .slideTxt {
border: magenta;
border-style: dashed;
height: 500px;
}
.carousel-button {
position: absolute;
background: none;
border: none;
outline: none;
font-size: 4rem;
top: 50%;
transform: translateY(-50%);
z-index: 2;
color: rgba(255, 255, 255, 0.5);
cursor: pointer;
padding: 0 0.5rem;
border-radius: 0.25rem;
background-color: rgba(0, 0, 0, 0.1);
transition: 0.5s;
}
.carousel-button:hover,
.carousel-button:focus {
background-color: rgba(0, 0, 0, 0.3);
color: #fff;
}
.carousel-button[data-carousel-btn="prev"] {
left: 1rem;
}
.carousel-button[data-carousel-btn="next"] {
right: 1rem;
}
<section class="row4 animateOnScroll" style="margin: 0 100px 100px 100px;">
<h2>don't just take it from us!</h2>
<div class="carouselContainer" data-carousel>
<button class="carousel-button" data-carousel-btn="prev">
❮
</button>
<button class="carousel-button" data-carousel-btn="next">
❯
</button>
<div class="carouselSlides">
<ul data-carousel-slides>
<li class="slide" data-carousel-slide data-active>
<div class="slideContent">
<div>
<img class="slideImg" src="./assets/imgPlaceholder.jpg">
</div>
<div class="slideTxt">
<div class="slideDesc">
<p style="color:black;">hello</p>
</div>
</div>
</div>
</li>
<li class="slide" data-carousel-slide>
<div class="slideContent">
<div>
<img class="slideImg" src="./assets/imgPlaceholder.jpg">
</div>
<div class="slideTxt">
<div class="slideDesc">
<p style="color:black;">hello</p>
</div>
</div>
</div>
</li>
<li class="slide" data-carousel-slide>
<div class="slideContent">
<div>
<img class="slideImg" src="./assets/imgPlaceholder.jpg">
</div>
<div class="slideTxt">
<div class="slideDesc">
<p style="color:black;">hello</p>
</div>
</div>
</div>
</ul>
</div>
</div>
</section>
part of your problem is your ul element is unstyled, its child li elements are going to stack as they normally do on top of each other. giving the ul element display: flex; will put your li's side by side.
If I were you, I would review each nested element of my tree and figure out its purpose, then remove it if not necessary. for example, div.carouselSlides does not seem like its serving any purpose that the ul could not do itself, at least in this small example.
Also, looking at an established project for implementation ideas (or just using it) might be a good idea . https://swiperjs.com/ is very established with powerful config options
Basically there should be 2 containers:
The element that is the parent of the <button>s and the "frame" that holds each slide. In the example it is article.box.
The element that is the parent of each div.slide in the example is section.frame.
Each container should be position: relative and all children of said containers should be position: absolute. Doing so will:
provide precision positioning of the <button>s and section.frame within the perimeters of article.box
allow all div.slide to hide underneath the visible layers (z-index:0+) with z-index: -1 and be visible with .active class at z-index: 1.
The JavaScript is optional, it's just written better but function should be basically the same.
View in full page mode, the image placeholder service does not have dynamic images.
const data = [
{img:"https://placem.at/people?random=1", cap:"People 1"},
{img:"https://placem.at/places?random=1", cap:"Places 2"},
{img:"https://placem.at/things?random=1", cap:"Things 3"}
];
const slides = genSlides(data);
const box = document.querySelector('.box')
const buttons = box.querySelectorAll("button");
buttons.forEach((button) => {
button.addEventListener("click", function(event) {
const offset = button.classList.contains("next") ? 1 : -1;
const active = box.querySelector(".active");
const actIdx = slides.indexOf(active);
const nextIdx = actIdx + offset;
active.classList.remove("active");
if (nextIdx < 0) {
return slides[slides.length + nextIdx].classList.add("active");
}
if (nextIdx >= slides.length) {
return slides[0].classList.add("active");
}
return slides[nextIdx].classList.add("active");
});
});
function genSlides(array) {
const frame = document.querySelector(".frame");
array.forEach(slide => {
frame.insertAdjacentHTML("beforeend", `
<div class="slide">
<figure>
<img src="${slide.img}" width="480">
<figcaption class="cap">${slide.cap}</figcaption>
</figure>
</div>`);
});
const slides = Array.from(frame.querySelectorAll(".slide"));
slides[0].classList.add("active");
return slides;
}
.box {
display: flex;
justify-content: center;
align-items: center;
position: relative;
width: 96vw;
min-height: 96vh;
border: 3px dashed #000;
}
.frame {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
/* The element that is the parent of all .slide should be relative so the
slides, which are absolute positioned, can sit within .frame's perimeter */
position: relative;
}
.slide {
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
/* All slides should be out of normal flow */
position: absolute;
/* All slides should be in the layer "under" the visible layer (z-index: 0+) */
z-index: -1;
opacity: 0;
animation: opacity 0.7s ease-in;
}
.active {
opacity: 1;
z-index: 1;
}
figure {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
max-height: 100%;
margin: 0;
padding: 0;
border-style: 1px dashed #000;
}
img {
object-fit: contain;
}
.cap {
min-width: 100%;
text-align: center;
white-space: pre;
}
button {
display: inline-flex;
justify-content: center;
align-items: center;
position: absolute;
top: 50%;
z-index: 2;
padding: 0 0.5rem;
border: none;
border-radius: 0.25rem;
outline: none;
font-size: 4rem;
color: rgba(255, 255, 255, 0.5);
background: none;
background-color: rgba(0, 0, 0, 0.1);
transform: translateY(-50%);
transition: 0.5s;
cursor: pointer;
}
button:hover,
button:focus {
color: #fff;
background-color: rgba(0, 0, 0, 0.3);
}
button:active {
color: rgba(0, 0, 0, 0.5);
background: none;
}
.prev {
left: 1rem;
}
.next {
right: 1rem;
}
<main>
<h2>Content Title</h2>
<article class="box">
<button class="prev">❮</button>
<button class="next">❯</button>
<section class="frame"></section>
</article>
</main>
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>
I have an image toggle triggered by button clicks and checkboxes. My code is currently working how I need it to, but I'm very new to JavaScript so I'm sure there is a cleaner way to do this.
A few notes:
This is for a client, so for confidentiality reasons, I cannot share the actual images, but the alt tags should tell the story.
I'm not allowed to use anything other than vanilla JS on the platform this will live, and all variables and functions have to have custom names, hence the funky naming.
var csDMU_checkbox = document.getElementById("csDMU_checkbox");
var csDMU_imageBefore = document.getElementById("before-image");
var csDMU_imageAfter = document.getElementById("after-image");
var csDMU_imageCombo = document.getElementById("combo-image");
var csDMU_switch = document.getElementById("switch");
var csDMU_toggle = document.getElementById("toggle");
function csDMU_toggleImage() {
if (csDMU_checkbox.checked == true) {
csDMU_imageBefore.style.display = "none";
csDMU_imageAfter.style.display = "block";
csDMU_imageCombo.style.display = "none";
} else {
csDMU_imageBefore.style.display = "block";
csDMU_imageAfter.style.display = "none";
csDMU_imageCombo.style.display = "none";
}
}
function csDMU_comboView() {
csDMU_imageCombo.style.display = "block";
csDMU_imageBefore.style.display = "none";
csDMU_imageAfter.style.display = "none";
csDMU_switch.style.display = "none";
csDMU_toggle.style.display = "block";
}
function csDMU_toggleView() {
csDMU_switch.style.display = "block";
csDMU_toggle.style.display = "none";
csDMU_imageBefore.style.display = "block";
csDMU_imageCombo.style.display = "none";
}
#import url('https://fonts.googleapis.com/css2?family=Libre+Franklin:ital,wght#0,400;0,700;1,400;1,700&display=swap');
body {
font-family: 'Libre Franklin', sans-serif;
}
.flexRow {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 119px;
height: 40px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #243b43;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 32px;
width: 33px;
right: 4px;
bottom: 3px;
background: transparent -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), color-stop(47%, #EDEDED), color-stop(73%, #D0D0D0), to(#E5E5E5)) 0% 0% no-repeat padding-box;
background: transparent linear-gradient(180deg, #FFFFFF 0%, #EDEDED 47%, #D0D0D0 73%, #E5E5E5 100%) 0% 0% no-repeat padding-box;
-webkit-box-shadow: 0px 3px 6px #00000029;
box-shadow: 0px 3px 6px #00000029;
border: 1px solid #FFFFFF;
-webkit-transition: .4s;
transition: .4s;
}
.slider:after {
content: "BEFORE";
display: block;
font-size: 14px;
line-height: 14px;
letter-spacing: 0.16px;
font-weight: bold;
color: #FFF;
position: relative;
top: 13px;
left: 10px;
}
input:checked + .slider {
background-color: #F26322;
}
input:focus + .slider {
-webkit-box-shadow: 0 0 1px #2196F3;
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(-75px);
transform: translateX(-75px);
}
input:checked + .slider:after {
content:'AFTER';
left: 50px;
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.combo-button,
.toggle-button{
width: 172px;
height: 40px;
margin-left: 20px;
border-radius: 100px;
border: 1px solid #C4C4C4;
color: #4a4b4d;
letter-spacing: 0.16px;
}
.combo-button:hover,
.combo-button:focus {
background-color: #002D5E;
color: #FFF;
}
.combo-button:focus {
outline: 0;
}
.toggle-button {
display: none;
width: 119px;
margin: 0;
}
.hand-img {
max-width: 700px;
margin-right: -20px;
display: block;
}
#after-image,
#combo-image {
display: none;
}
<html>
<body>
<div id="image-change">
<img src="" alt="before image" class="hand-img" id="before-image" />
<img src="" alt="after image" class="hand-img" id="after-image" />
<img src="" alt="combo image" class="hand-img" id="combo-image" />
</div>
<div class="flexRow">
<label class="switch" id="switch">
<input type="checkbox" id="csDMU_checkbox" onclick="csDMU_toggleImage()">
<span class="slider round"></span>
</label>
<button class="toggle-button" id="toggle" onclick="csDMU_toggleView()">TOGGLE VIEW</button>
<button class="combo-button" onclick="csDMU_comboView()">COMPARISON</button>
</div>
</body>
</html>
Well you could minimize your JS code by first selecting all the elements using one line selector, note that you need to write the selected elements in their order in HTML to get them right because we're destructuring the returned node list into variables so the order matters because it's an array and not an object, then you are writing repeatedly element.style.display = "some value" so you can write a function to do that using an array of elements as input and their display value to set as two arrays and just loop over the first array of the elements and assign the correct CSS display value according to the index, and use a ternary expression instead of If-Else statement too write less code, here is the full JS code
let [csDMU_imageBefore, csDMU_imageAfter, csDMU_imageCombo, csDMU_switch, csDMU_checkbox, csDMU_toggle] = document.querySelectorAll("#before-image, #after-image, #combo-image, #switch, #csDMU_checkbox, #toggle");
const setCssDisplay = (elements, values) => elements.forEach((element, index) => element.style.display = values[index]);
function csDMU_toggleImage() {
setCssDisplay([csDMU_imageBefore, csDMU_imageAfter, csDMU_imageCombo], csDMU_checkbox.checked ? ["none", "block", "none"] : ["block", "none", "none"]);
}
function csDMU_comboView() {
setCssDisplay([csDMU_imageCombo, csDMU_imageBefore, csDMU_imageAfter, csDMU_switch, csDMU_toggle], ["block", "none", "none", "none", "block"]);
}
function csDMU_toggleView() {
setCssDisplay([csDMU_switch, csDMU_toggle, csDMU_imageBefore, csDMU_imageCombo], ["block", "none", "block", "none"]);
}
Don't know how to make a static slide , got this sliding down animation.
What should I change?
Maybe I made smth with 'position' property?
Or with positioning in general?
Or my JS sucks....
#slides {
position: relative;
height: 500px;
padding: 0px;
margin: 0px;
list-style-type: none;
}
.slide {
width: 600px;
height: 500px;
margin-top: 0px;
margin-left: 500px;
opacity: 0;
z-index: 1;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
-o-transition: opacity 1s;
transition: opacity 1s;
}
.showing {
opacity: 1;
z-index: 2;
}
.controls {
display: none;
}
.slide {
font-size: 40px;
padding: 70px;
box-sizing: border-box;
background: #333;
color: #fff;
background-size: cover;
}
.controls {
background: #333;
color: #fff;
border: none;
padding: 20px 0px;
font-size: 20px;
cursor: pointer;
border: 2px solid #fff;
margin: 10px 0px 0px 10px;
display: flex;
justify-content: center;
align-items: center;
width: 70px;
position: relative;
left: 38%;
margin-top: 25px;
}
.controls:hover,
.controls:focus {
background: #eee;
color: #333;
}
.buttons {
position: absolute;
left: 0px;
top: 0px;
z-index: 20;
font-size: 0px;
}
.controls:nth-of-type(2), .controls:nth-of-type(3) {
width: 9%;
}
// Some JS
var controls = document.querySelectorAll('.controls');
for(var i=0; i<controls.length; i++){
controls[i].style.display = 'inline-block';
}
var slides = document.querySelectorAll('#slides .slide');
var currentSlide = 0;
var slideInterval = setInterval(nextSlide,2000);
function nextSlide(){
goToSlide(currentSlide+1);
}
function previousSlide(){
goToSlide(currentSlide-1);
}
function goToSlide(n){
slides[currentSlide].className = 'slide';
currentSlide = (n+slides.length)%slides.length;
slides[currentSlide].className = 'slide showing';
}
var playing = true;
var pauseButton = document.getElementById('pause');
function pauseSlideshow(){
pauseButton.innerHTML = '►'; // play character
playing = false;
clearInterval(slideInterval);
}
function playSlideshow(){
pauseButton.innerHTML = '❚❚'; // pause character
playing = true;
slideInterval = setInterval(nextSlide,2000);
}
pauseButton.onclick = function(){
if(playing){ pauseSlideshow(); }
else{ playSlideshow(); }
};
var next = document.getElementById('next');
var previous = document.getElementById('previous');
next.onclick = function(){
pauseSlideshow();
nextSlide();
};
previous.onclick = function(){
pauseSlideshow();
previousSlide();
};
Sorry, that it is without comments :(
You don't want to use the opacity property to hide the image, it will still "occupy the space" and therefore move the elements down,
You'll need to use the display which will simply not draw anything for this element and not allocate any space for it.
In your CSS, replace opacity: 0 in the .slide by display: none
and replace opacity: 1 in the .showing by display: block
It should fix your problem
I made a content tile that when clicked, activates another part of the screen. On the tile, I have a couple links that, when clicked, go to new pages. I made a non-javascript version that works fine.
No javascript:
https://jsfiddle.net/raazqqks/2/
HTML:
<div class="tile activeTile" id="response0">
<div class="responseContainer">
<div class="left">
<h4 class="title">
<a class="topLink" href="javascript:alert('Link clicked')">Title</a>
</h4>
<p>Foo bar</p>
<p>Foo bar?</p>
<p class="extra">
<a class="topLink" href="javascript:alert('Link clicked')">Extra foo bar!</a>
</p>
</div>
<div class="bonus">
<p>Bonus</p>
</div>
<a class="noJavaLink" id="0" href="javascript:alert('Tile clicked');"></a>
</div>
</div>
CSS:
.responseContainer {
position: relative;
overflow: hidden;
z-index: 0;
transition: all linear .2s;
border: 1px solid grey;
border-radius: 4px;
background-color: white;
}
.responseContainer p {
margin: 0;
}
.tile {
width: 80%;
text-align: left;
margin: 16px 48px 16px 32px;
margin-top: 0;
transition: all linear .2s;
z-index: 0;
border-radius: 4px;
background-repeat: no-repeat;
}
.activeTile {
width: 90%;
border-radius: 4px;
color: white;
}
.activeTile > div {
background-color: rgba(33, 33, 33, .5);
}
.left {
float: left;
margin: 10px;
margin-top: -10px;
max-width: 50%;
}
.title {
font-size: 1.2em;
}
.title h4 {
margin: 20px 0 20px;
}
.bonus {
float: right;
margin-top: 10px;
margin: 10px;
font-size: 1.5em;
max-width: 50%;
}
.topLink {
position: relative;
z-index: 100;
}
.noJavaLink {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
text-decoration: none;
z-index: 10;
background-color: white;
border-radius: 4px;
opacity: 0;
filter: alpha(opacity=0);
cursor: pointer;
}
.active .noJavaLink {
pointer-events: none;
cursor: default;
}
I want to add simple animations to it, so if javascript is available, this version loads.
Javascript:
https://jsfiddle.net/n4svaLut/
Javascript:
document.addEventListener("DOMContentLoaded", setJavascriptTileAnimation(), false );
/* Set onclick events for tile animation
|
*/
function setJavascriptTileAnimation() {
var tiles = document.getElementsByClassName('tile')
var links = document.getElementsByClassName('noJavaLink');
for (var i = 0; i < tiles.length; i++) {
var tile = tiles[i];
var id = tile['id'];
tile.onclick = function() {
changeActiveTile(this.id);
//return false;
};
links[i].removeAttribute('href');
};
}
/* Toggle active tile
|
*/
function changeActiveTile(id) {
id_number = getIdNumber(id);
active_tile = document.getElementsByClassName('tile activeTile')[0];
active_tile.classList.remove('activeTile');
setTimeout(function() {
tile = document.getElementById(id);
tile.classList.add('activeTile');
}, 300);
}
function getIdNumber(id) {
return id.replace( /^\D+/g, '');
}
Notice how the links only work on a double click. Ive been playing around with this for two days and havent made any progress at all. Any ideas?
SOLUTION: Remove 'return false' from the onclick setter.