How to cancel sliding down animation and make just static slide - javascript

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

Related

How to change the active tab in a responsive navigation bar in HTML,CSS,JS?

In this navigation bar when the mouse hovers over the different links of the navigation bar the animation box comes on the box where the mouse is hovering but when the user clicks the new link the animation box does not stay on the active link it resets to the top item in the navigation bar.
I tried to change the position of the animation box using JavaScript but I did not succeed
I am changing the position of the animation box using top: property
Please help would be really appreciated.
please change the css <link rel="stylesheet" href="../css/home.css"> link in html file according to you.
Please run the code snippet to get a better view of the question.
sorry for any wrong grammar.
var links = document.getElementsByClassName('l')
for (var i = 0; i < links.length; i++) {
links[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
var eid = current[0].id
switch (eid) {
case 1:
style = document.createElement('style')
style.innerHTMl = ".animation {top:0px}"
document.body.appendChild(style)
break;
case 2:
style = document.createElement('style')
style.innerHTMl = ".animation {top:50px}"
document.body.appendChild(style)
break;
case 3:
style = document.createElement('style')
style.innerHTMl = ".animation {top:100px}"
document.body.appendChild(style)
break;
}
current[0].className = "l";
this.className = "l" + " " + "active";
})
}
#import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');
body {
background: #2c3e5e;
font-family: 'Open Sans', sans-serif;
}
nav {
display: block;
background-color: #34495e;
position: relative;
margin: 100px auto 0;
border-radius: 8px;
font-size: 0;
width: 220px;
height: auto;
box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.1);
}
nav a {
line-height: 50px;
color: white;
text-transform: uppercase;
position: relative;
z-index: 1;
text-decoration: none;
font-size: 15px;
display: block;
text-align: center;
}
nav .animation {
position: absolute;
height: 50px;
width: 100%;
top: 0px;
z-index: 0;
background: #1abc9c;
border-radius: 8px;
transition: all .5s ease 0s
}
nav a:nth-child(1):hover~.animation {
top: 0;
}
nav a:nth-child(2):hover~.animation {
top: 50px;
}
nav a:nth-child(3):hover~.animation {
top: 100px;
}
<nav>
Student BioData
Student Acadmics
Complaint Record
<div id='animation' class="animation"></div>
</nav>
Your eid is always equal 3, because you are accessing same object by reference every time, that's why your code doesn't work. It's happening, because you declared var i instead of let i, so i is equal 3 for every link, so instead of (0,1,2) you have (3,3,3). Be careful while using var.
Also your code can be simplified to this:
const links = document.getElementsByClassName('l')
const animation = document.getElementById('animation')
for (let i = 0; i < links.length; i++) {
links[i].addEventListener("click", function() {
animation.style.top = (i * 50) + "px"
})
}
#import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');
body {
background: #2c3e5e;
font-family: 'Open Sans', sans-serif;
}
nav {
display: block;
background-color: #34495e;
position: relative;
margin: 0 auto;
border-radius: 8px;
font-size: 0;
width: 220px;
height: auto;
box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.1);
}
nav a {
line-height: 50px;
color: white;
text-transform: uppercase;
position: relative;
z-index: 1;
text-decoration: none;
font-size: 15px;
display: block;
text-align: center;
}
nav .animation {
position: absolute;
height: 50px;
width: 100%;
top: 0px;
z-index: 0;
background: #1abc9c;
border-radius: 8px;
transition: all .5s ease 0s
}
nav a:nth-child(1):hover~.animation {
top: 0 !important;
}
nav a:nth-child(2):hover~.animation {
top: 50px !important;
}
nav a:nth-child(3):hover~.animation {
top: 100px !important;
}
<nav>
Student BioData
Student Acadmics
Complaint Record
<div id='animation' class="animation"></div>
</nav>
Sorry I have put most your script inside comment but I solved your problem
Here is the script
<head>
<style type="text/css">
#import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');
body {
background: #2c3e5e;
font-family: 'Open Sans', sans-serif;
}
nav {
display: block;
background-color: #34495e;
position: relative;
margin: 100px auto 0;
border-radius: 8px;
font-size: 0;
width: 220px;
height: auto;
box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.1), 0 0 300px #000;
}
nav a {
line-height: 50px;
color: white;
text-transform: uppercase;
position: relative;
z-index: 1;
text-decoration: none;
font-size: 15px;
display: block;
text-align: center;
}
nav .animation {
position:absolute;
height: 50px;
width: 100%;
top: 0px;
z-index: 0;
background: #1abc9c;
border-radius: 8px;
transition: all .5s ease 0s;
}
/* nav a:nth-child(1):hover~.animation {
top: 0;
}
nav a:nth-child(2):hover~.animation {
top: 50px;
}
nav a:nth-child(3):hover~.animation {
top: 100px;
} */
</style>
<title>Home</title>
</head>
<body>
<nav>
Student BioData
Student Acadmics
Complaint Record
<div id='animation' class="animation" ></div>
</nav>
<script>/*
var links = document.getElementsByClassName('l')
for (var i = 0; i < links.length; i++) {
links[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
var eid = current[0].id
switch (eid) {
case 1:
style = document.createElement('style')
style.innerHTMl = ".animation {top:0px}"
document.body.appendChild(style)
break;
case 2:
style = document.createElement('style')
style.innerHTMl = ".animation {top:50px}"
document.body.appendChild(style)
break;
case 3:
style = document.createElement('style')
style.innerHTMl = ".animation {top:100px}"
document.body.appendChild(style)
break;
}
current[0].className = "l";
this.className = "l" + " " + "active";
})
}*/
var links = document.querySelectorAll(".l");
for(i=0;i<=links.length;i++){
links[i].addEventListener("click", function(){
let e = this.id;
document.querySelector(".animation").style.top = Math.floor((e-1)*50) + "px" ;
});
}
</script>
</body>
Main change:
var links=document.querySelectorAll(".l");
for(i=0;i<=links.length;i++){
links[i].addEventListener("click",function(){
let e = this.id;
document.querySelector(".animation").style.top = Math.floor(50*(e-1)) + "px"
});
}

Javascript conflict: Div scrolling speed control & image shrink on scroll together

I've been wrestling with this problem for a while without success, so I'm hoping someone with greater knowledge can offer a solution.
By using a script to independently control the scroll speeds of specific divs, I've managed to create an effect along the lines of parallax scrolling:
https://neilwhitedesign.co.uk/pt_testing_area/index(scrolling).html
However, what I would also like to add, is a second script to reduce the size of the logo when the page is scrolls:
https://neilwhitedesign.co.uk/pt_testing_area/index(headershrink).html
Independently, these scripts are working exactly as I want them, but when I try to combine the two, there is a conflict and only the scrolling effect works.
Looking at similar questions posted previously, one solution was to add a further script between the two, to call a noConflict.
However, while adding this now makes the shrinking image effect work, it does so at the expense of the scrolling effect.
Is what I'm trying to achieve possible?
Is there a simple solution to get around the conflict?
Please find my html and css below:
HTML
window.onscroll = function() {
growShrinkLogo()
};
var Logo = document.getElementById("Logo");
var endOfDocumentTop = 90;
var size = 0;
function growShrinkLogo() {
var scroll = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 90;
if (size == 0 && scroll > endOfDocumentTop) {
Logo.className = 'smallLogo';
size = 1;
} else if (size == 1 && scroll <= endOfDocumentTop) {
Logo.className = 'largeLogo';
size = 0;
}
}
$.fn.moveIt = function() {
var $window = $(window);
var instances = [];
$(this).each(function() {
instances.push(new moveItItem($(this)));
});
window.onscroll = function() {
var scrollTop = $window.scrollTop();
instances.forEach(function(inst) {
inst.update(scrollTop);
});
}
}
var moveItItem = function(el) {
this.el = $(el);
this.speed = parseInt(this.el.attr('data-scroll-speed'));
};
moveItItem.prototype.update = function(scrollTop) {
var pos = scrollTop / this.speed;
this.el.css('transform', 'translateY(' + +pos + 'px)');
};
$(function() {
$('[data-scroll-speed]').moveIt();
});
#charset "utf-8";
/* CSS Document */
/* 2. Clearfix*/
.clearfix:after {
clear: both;
}
.clearfix {
zoom: 1
}
/* 3. Images*/
a img {
border: none;
}
img {
max-width: 100%;
vertical-align: middle;
}
/* 4. Structure*/
body {
background: #fff;
color: #555;
line-height: 1.9;
margin: 0 auto;
}
.header {
background: white;
display: block;
margin: 0 auto;
position: fixed;
text-align: left;
width: 100%;
z-index: 99;
}
.parallax_container {
width: 100%;
}
.parallax {
padding-top: 50px;
}
.tagline {
color: white;
font-size: 75px;
position: absolute;
top: 50%;
bottom: 50%;
left: 5%;
right: 5%;
text-align: center;
cursor: pointer;
line-height: 1.2;
z-index: 97;
}
.content {
background: yellow;
height: 900px;
z-index: 98;
}
/* 5. Logo*/
.logo_container {
width: inherit;
padding: 10px;
}
#Logo {
-webkit-transition: width .5s ease;
-o-transition: width .5s ease;
transition: width .5s ease;
}
.largeLogo {
width: 350px;
}
.smallLogo {
width: 250px;
}
/* 6. Footer */
footer {
display: block;
height: 50px;
font-size: 13px;
margin: 0 auto;
padding: 25px 0 0 0;
position: relative;
text-align: center;
width: inherit;
}
<link rel="stylesheet" type="text/css" href="https://neilwhitedesign.co.uk/pt_testing_area/css.css" />
<body>
<div class="header">
<div class="logo_container"><img src="https://neilwhitedesign.co.uk/pt_testing_area/logo.png" class="largeLogo" id='Logo'>
</div>
</div>
<div class="parallax_container">
<div class="tagline" data-scroll-speed="3">This is the tagline</div>
<div class="parallax" data-scroll-speed="2"><img src="https://neilwhitedesign.co.uk/pt_testing_area/landscape.jpg" /></div>
</div>
<div class="content" data-scroll-speed="100">Content Area</div>
<footer>© 2021
<script src="https://neilwhitedesign.co.uk/pt_testing_area/js/copyright.js"></script> | All rights reserved.</footer>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</body>
Any guidance would be greatly appreciated.
Thanks
Neil White
You should never use on* handlers (unless you're creating a brand new element from in-memory) use .addEventListener() instead or the jQuery method .on() - that way handlers are attached to an element, not overwritten.
Place <script> tags (all of them) right before the closing </body> tag
Use classList.toggle or jQuery's .toggleClass()
You don't need two classes for big and small logo - only one.
jQuery plugins should use return to allow for methods chainability
Here's a remake of the plugin and your scripts:
// moveIt jQuery plugin
$.fn.moveIt = function() {
const $window = $(window);
const instances = [];
const updateItems = () => {
const scrTop = $window.scrollTop();
instances.forEach((inst) => inst.update(scrTop));
};
$window.on("scroll", updateItems); // Do on scroll
updateItems(); // and on page load
// Use "return" to allow $ methods chainability
return this.each(function(i, el) {
instances.push(new moveItItem(el));
});
}
function moveItItem(el) {
this.el = $(el);
this.speed = parseInt(this.el.data("scroll-speed"));
};
moveItItem.prototype.update = function(scrTop) {
this.el.css({transform: `translateY(${scrTop / this.speed}px)`});
};
// App
const $window = $(window);
const $logo = $("#Logo");
const docTop = 90;
function growShrinkLogo() {
$logo.toggleClass("small", $window.scrollTop() > docTop);
}
$window.on("scroll", growShrinkLogo); // Do on scroll
growShrinkLogo(); // and on page load
// moveIt plugin init:
$('[data-scroll-speed]').moveIt();
#charset "utf-8";
.clearfix:after {
clear: both;
}
.clearfix {
zoom: 1
}
a img {
border: none;
}
img {
max-width: 100%;
vertical-align: middle;
}
body {
background: #fff;
color: #555;
line-height: 1.9;
margin: 0 auto;
}
.header {
background: white;
display: block;
margin: 0 auto;
position: fixed;
text-align: left;
width: 100%;
z-index: 99;
}
.parallax_container {
width: 100%;
}
.parallax {
padding-top: 50px;
}
.tagline {
color: white;
font-size: 75px;
position: absolute;
top: 50%;
bottom: 50%;
left: 5%;
right: 5%;
text-align: center;
cursor: pointer;
line-height: 1.2;
z-index: 97;
}
.content {
background: yellow;
height: 900px;
z-index: 98;
}
.logo_container {
width: inherit;
padding: 10px;
}
#Logo {
-webkit-transition: width .5s ease;
-o-transition: width .5s ease;
transition: width .5s ease;
width: 350px;
}
#Logo.small {
width: 250px;
}
footer {
display: block;
height: 50px;
font-size: 13px;
margin: 0 auto;
padding: 25px 0 0 0;
position: relative;
text-align: center;
width: inherit;
}
<div class="header">
<div class="logo_container"><img src="https://neilwhitedesign.co.uk/pt_testing_area/logo.png" class="largeLogo" id='Logo'>
</div>
</div>
<div class="parallax_container">
<div class="tagline" data-scroll-speed="3">This is the tagline</div>
<div class="parallax" data-scroll-speed="2"><img src="https://neilwhitedesign.co.uk/pt_testing_area/landscape.jpg" /></div>
</div>
<div class="content" data-scroll-speed="100">Content Area</div>
<footer>© 2021 | All rights reserved.</footer>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
It is because you declare window.onscroll twice and therefor it overwrites the first declaration. You just have to add the call of growShrinkLogo() to the second window.onscroll.
Working example:
var Logo = document.getElementById("Logo");
var endOfDocumentTop = 90;
var size = 0;
function growShrinkLogo() {
var scroll = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 90;
if (size == 0 && scroll > endOfDocumentTop) {
Logo.className = 'smallLogo';
size = 1;
} else if (size == 1 && scroll <= endOfDocumentTop) {
Logo.className = 'largeLogo';
size = 0;
}
}
$.fn.moveIt = function() {
var $window = $(window);
var instances = [];
$(this).each(function() {
instances.push(new moveItItem($(this)));
});
window.onscroll = function() {
growShrinkLogo();
var scrollTop = $window.scrollTop();
instances.forEach(function(inst) {
inst.update(scrollTop);
});
}
}
var moveItItem = function(el) {
this.el = $(el);
this.speed = parseInt(this.el.attr('data-scroll-speed'));
};
moveItItem.prototype.update = function(scrollTop) {
var pos = scrollTop / this.speed;
this.el.css('transform', 'translateY(' + +pos + 'px)');
};
$(function() {
$('[data-scroll-speed]').moveIt();
});
#charset "utf-8";
/* CSS Document */
/* 2. Clearfix*/
.clearfix:after {
clear: both;
}
.clearfix {
zoom: 1
}
/* 3. Images*/
a img {
border: none;
}
img {
max-width: 100%;
vertical-align: middle;
}
/* 4. Structure*/
body {
background: #fff;
color: #555;
line-height: 1.9;
margin: 0 auto;
}
.header {
background: white;
display: block;
margin: 0 auto;
position: fixed;
text-align: left;
width: 100%;
z-index: 99;
}
.parallax_container {
width: 100%;
}
.parallax {
padding-top: 50px;
}
.tagline {
color: white;
font-size: 75px;
position: absolute;
top: 50%;
bottom: 50%;
left: 5%;
right: 5%;
text-align: center;
cursor: pointer;
line-height: 1.2;
z-index: 97;
}
.content {
background: yellow;
height: 900px;
z-index: 98;
}
/* 5. Logo*/
.logo_container {
width: inherit;
padding: 10px;
}
#Logo {
-webkit-transition: width .5s ease;
-o-transition: width .5s ease;
transition: width .5s ease;
}
.largeLogo {
width: 350px;
}
.smallLogo {
width: 250px;
}
/* 6. Footer */
footer {
display: block;
height: 50px;
font-size: 13px;
margin: 0 auto;
padding: 25px 0 0 0;
position: relative;
text-align: center;
width: inherit;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="header">
<div class="logo_container">
<img src="https://neilwhitedesign.co.uk/pt_testing_area/logo.png" class="largeLogo" id='Logo'>
</div>
</div>
<div class="parallax_container">
<div class="tagline" data-scroll-speed="3">
This is the tagline
</div>
<div class="parallax" data-scroll-speed="2">
<img src="https://neilwhitedesign.co.uk/pt_testing_area/landscape.jpg" />
</div>
</div>
<div class="content" data-scroll-speed="100">
Content Area
</div>
<footer>
© 2021 | All rights reserved.
</footer>

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)`
}

Javascript refactoring help needed

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"]);
}

Toggle button animation

I have a toggle button to switch the website background color from black to white (and vice versa). It works ok, but I want the slider to move slowly (in 1 second, not instantly) when I click on it. The code:
var change = function() {
var backgr = document.body,
slider = document.getElementById('slider');
if (backgr.style.backgroundColor == 'white') {
backgr.style.backgroundColor = 'black';
slider.style.float = 'right';
} else {
backgr.style.backgroundColor = 'white';
slider.style.float = 'left';
}
}
body {
background-color: black;
}
#toggle {
width: 30px;
height: 16px;
background-color: orange;
padding: 0;
border: none;
border-radius: 16px;
}
#slider {
width: 14px;
height: 14px;
background-color: white;
margin: 1px;
border-radius: 50%;
float: right;
}
<button id='toggle' onclick="change()">
<span id='slider'></span>
</button>
Not sure if you have to animate the background-color or the button so I have animated both with a CSS transition, so keep just what you need.
For the button I've simply changed the margin-right (via calc()) keeping the float: right (which it can't be animated)
Also the JS part is simplified: toggling a class on the body element is enough and you can keep off your style from Javascript so as a result your code is more mantainable.
var body = document.body;
var change = function() {
body.classList.toggle('active');
}
body {
background-color: black;
transition: background-color 1s;
}
body.active {
background-color: white;
}
#toggle {
width: 30px;
height: 16px;
background-color: orange;
padding: 0;
border: none;
border-radius: 16px;
}
#slider {
width: 14px;
height: 14px;
background-color: white;
margin: 1px;
transition: margin 1s;
border-radius: 50%;
float: right;
}
.active #slider {
margin-right: calc(100% - 15px);
}
<button id='toggle' onclick="change()">
<span id='slider'></span>
</button>
Rather than using a button, I'd reskin a checkbox like this. This is handy as it keeps track of its own boolean value.
Then based on whether or not it's checked you can do whatever.
Below I've used transform and transition to animate the sliding you can see this in the CSS.
function toggleChange(e) {
let bodyStyle = document.querySelector('body').style;
if (e.target.checked) {
bodyStyle.background = "#000";
} else {
bodyStyle.background = "#FFF";
}
}
.switch[type=checkbox] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
position: relative;
width: 30px;
height: 16px;
background-color: orange;
border-radius: 16px;
}
.switch[type=checkbox]::after {
content: '';
position: absolute;
background: #FFF;
transition: all .2s ease-in-out;
border-radius: 7px;
width: 14px;
height: 14px;
margin: 1px;
}
.switch[type=checkbox]:checked::after {
transform: translateX(14px);
}
<input type="checkbox" onchange="toggleChange(event)" class="switch" />
I hope this is helpful.
Use transition: left 1000ms ease;
and position: relative;
Then change the left property in the script instead of changing float:
var change = function() {
var backgr = document.body,
slider = document.getElementById('slider');
if (backgr.style.backgroundColor == 'white') {
backgr.style.backgroundColor = 'black';
slider.style.left = 0; // NEW LINE
} else {
backgr.style.backgroundColor = 'white';
slider.style.left = "15px"; // NEW LINE
}
}
body {
background-color: black;
}
#toggle {
width: 30px;
height: 16px;
background-color: orange;
padding: 0;
border: none;
border-radius: 16px;
}
#slider {
width: 14px;
height: 14px;
background-color: white;
margin: 1px;
border-radius: 50%;
float: left; /* NEW LINE */
position: relative; /* NEW LINE */
transition: left 1000ms ease; /* NEW LINE */
left: 0; /* NEW LINE */
}
<button id='toggle' onclick="change()">
<span id='slider'></span>
</button>
Instead of float, I think you should use css that can by used with transition. if you place your sldier with a position for example, you can add a transition on the position with a 1sec duration and it will works as you want

Categories

Resources