Hide and show same element on click with javascript [duplicate] - javascript

This question already has answers here:
How to create javascript delay function [duplicate]
(3 answers)
What is the JavaScript version of sleep()?
(91 answers)
Closed 4 years ago.
I am trying to get a bar to hide and then show again in one click. Do I need to put some kind of time out when re-adding the class?
var button = document.querySelector('.btn');
button.addEventListener('click', function() {
document.querySelector('.bar').classList.remove('animateBar');
document.querySelector('.bar').classList.add('animateBar');
});
* {
padding: 0;
margin: 0;
}
.wrap {
width: 100%;
height: 100vh;
overflow: hidden;
position: relative
}
.bar {
position: absolute;
bottom: 0;
height: 100px;
width: 100%;
background-color: black;
transform: translateY(100%);
transition: transform 1s;
}
.animateBar {
transform: translateY(0);
transition: transform 1s;
}
.btn {
position: relative;
display: block;
text-align: center;
cursor: pointer;
}
<div class="wrap">
<div class="bar animateBar"></div>
<div class="btn">hide/show</div>
</div>

use setTimeout() between removing and adding the class
var button = document.querySelector('.btn');
button.addEventListener('click', function() {
document.querySelector('.bar').classList.remove('animateBar');
setTimeout(function(){
document.querySelector('.bar').classList.add('animateBar');
}, 1000);
});
* {
padding: 0;
margin: 0;
}
.wrap {
width: 100%;
height: 100vh;
overflow: hidden;
position: relative
}
.bar {
position: absolute;
bottom: 0;
height: 100px;
width: 100%;
background-color: black;
transform: translateY(100%);
transition: transform 1s;
}
.animateBar {
transform: translateY(0);
transition: transform 1s;
}
.btn {
position: relative;
display: block;
text-align: center;
cursor: pointer;
}
<div class="wrap">
<div class="bar animateBar"></div>
<div class="btn">hide/show</div>
</div>

Yes you need to use setTimeout with a delay. Try the following.
var button = document.querySelector('.btn');
button.addEventListener('click', function() {
document.querySelector('.bar').classList.remove('animateBar');
setTimeout(() => {
document.querySelector('.bar').classList.add('animateBar');
}, 800);
});
* {
padding: 0;
margin: 0;
}
.wrap {
width: 100%;
height: 100vh;
overflow: hidden;
position: relative
}
.bar {
position: absolute;
bottom: 0;
height: 100px;
width: 100%;
background-color: black;
transform: translateY(100%);
transition: transform 1s;
}
.animateBar {
transform: translateY(0);
transition: transform 1s;
}
.btn {
position: relative;
display: block;
text-align: center;
cursor: pointer;
}
<div class="wrap">
<div class="bar animateBar"></div>
<div class="btn">hide/show</div>
</div>

var button = document.querySelector('.btn');
button.addEventListener('click', function() {
document.querySelector('.bar').classList.remove('animateBar');
setTimeout(() => {
document.querySelector('.bar').classList.add('animateBar');
}, 1000);
});
This should work

Related

How to create a square box in which the border of the box will be filled by color depending on the value given on the box?

Just like the above image or an idea or reference to achieve this design, I appreciate the help or suggestion given by community thank you
I have got reference of progress bar which is circular but not able find an approach to solve it.
const boxes = document.querySelectorAll(".box");
const colors = ['red', 'blue', 'green', 'yellow', 'orange', 'violet']
boxes.forEach((box) => {
const insideContent = box.innerText;
box.style.border = `6px solid ${colors[insideContent]}`
})
#app {
display: flex;
}
.box {
width: 50px;
height: 50px;
margin: 10px;
background-color: cyan;
display: flex;
justify-content: center;
align-items: center;
}
<div id="app">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
As per your question I think this is what you are trying to achieve.
First define a pseudo class root
:root {
--color-val: blue;
}
Note: In order to use the --color-val you need to write it as color: var(--color-var) in CSS
Second use JavaScript to update the variable --color-val
let colors =
var root = document.querySelector(':root');
const delay = ms => new Promise(res => setTimeout(res, ms));
const colorChange = async () => {
await delay(1000);
color = colors[Math.floor(Math.random() * colors.length)]
console.log(color)
root.style.setProperty('--color-val', color);
};
colorChange()
Note:
Add the color list you want to select from or go to CodePen for a list of 1000+ hex codes.
Promise are used for asynchronous function and can be skipped by using setTimeOut for a delayed loop or if used with another eventlistener.
I apologize if I misunderstood the question. Wrote in a hurry and without beautyful visualisation, if you disassemble the principle, you can customize it.
h1 {
display: block;
margin:0 auto;
text-align: center;
padding-top:20%;
}
.container {
display:flex;
width: 150px;
height: 150px;
border: 1px solid black;
z-index: 110;
margin:0;
margin: -10px;
}
.top {
display:block;
background-color: green;
height: 24px;
width: 150px; /* gorizontal top */
animation: top 1s linear;
animation-fill-mode: forwards;
}
#keyframes top {
0% {
width: 0px;
}
100% {
width: 150px;
}
}
.right {
background-color: green;
height: 0%;/* right */
width: 32px;
animation: right 1s linear;
animation-fill-mode: forwards;
animation-delay: 1s;
z-index: 10;
}
#keyframes right {
0% {
height: 0%;
}
100% {
height: 100%;
}
}
.box {
position: fixed;
top: 32.5px;
left: 32.5px;
width: 100px;
height: 100px;
border: 1px solid black;
margin: auto;
z-index: 120;
margin: -10px -10px;
}
.bottom {
position: absolute;
top: 123px;
left: 150px;
background-color: green;
width: 0px;
height: 27px;
z-index: 10;
animation: bottom 1s linear;
animation-fill-mode: forwards;
animation-delay: 2s;
/* animation-direction: reverse; */
}
#keyframes bottom {
0% {
transform: translate(0,0);
}
100% {
transform: translate(-250px,0);
-webkit-transform: translate(-250px,0); /** Safari & Chrome **/
-o-transform: translate(-250px,0); /** Opera **/
-moz-transform: translate(-250px,0); /** Firefox **/
width: 250px;
}
}
.left {
position: absolute;
top: 122px;
background-color: green;
width: 25px;
height: 0px;
animation: left 1s linear;
animation-fill-mode: forwards;
animation-delay: 3s;
}
#keyframes left {
0% {
transform: translate(0,0);
}
100% {
transform: translate(0,-250px);
-webkit-transform: translate(0,-250px); /** Safari & Chrome **/
-o-transform: translate(0,-250px); /** Opera **/
-moz-transform: translate(0,-250px); /** Firefox **/
height: 277px;
}
}
<div class='head'>
<div class='container'>
<div class='top'></div>
<div class='box'>
<h1 id='timer'>
1
</h1>
</div>
<div class='right'></div>
<div class='bottom'></div>
<div class='left'></div>
</div>
</div>
<script type="text/javascript">
init()
function init()
{
sec = 0;
setInterval(tick, 1000);
}
function tick()
{ if (sec<3) { sec++
document.getElementById("timer").
childNodes[0].nodeValue = sec;
} else {
clearInterval(0);
}
}
</script>
Also, instead of the SetInterval script, you can take values from your block width and height styles and output a mathematical calculation in h1 instead of a stopwatch.
upd: After your comment, I decided to do what I wrote about above. You can play with values and math, I add a snippet of another solution that changes the progress bar from the entered values within the entered range. (of course, it would be easier on react than on pure js)
function grade () {
let grade = +document.getElementById("grade").value;
let range = +document.getElementById("range").value;
document.getElementById("timer").innerHTML = `${grade}/${range}`;
progress(grade,range)
}
function progress (value, grade) {
document.getElementById('1').style.backgroundColor = `white`
document.getElementById("left").className = "noactive";
document.getElementById('top').style.width = `0%`
document.getElementById('right').style.height = `0%`
document.getElementById('bottom').style.width = `0%`
let GradeValuSide = grade/4;
if (value <= GradeValuSide) {
document.getElementById('top').style.width =
`${value/GradeValuSide*100}%`
} else if (value > GradeValuSide && value <= (GradeValuSide*2)) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height =
`${(value-GradeValuSide)/GradeValuSide*100}%`
} else if (value >= grade/2 && value < (grade/4)*3) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height = `100%`
document.getElementById('bottom').style.width =
`${((((value-(GradeValuSide*2)) / GradeValuSide) *100) / 100) *27}%`
} else if (value >= grade-(grade/4) /* && value < value + 1 */) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height = `100%`
document.getElementById('bottom').style.width = `100%`
document.getElementById('1').style.backgroundColor = `green`
document.getElementById("left").className = "left";
document.getElementById('left').style.height =
`${(40 - (40 * ((((value-(GradeValuSide*3)) * 100) / GradeValuSide)/ 100)))}%`
}
}
h1 {
font-size:20px;
position: absolute;
left: 40px;
display: block;
margin: 0 auto;
align-items: center;
padding-top:10%;
}
.container {
display:flex;
width: 150px;
height: 150px;
border: 1px solid black;
margin:0;
margin: -10px;
}
div.top {
display:block;
background-color: green;
height: 24px;
width: 0%; /* gorizontal top */
z-index:999;
}
div.right {
position:relative;
background-color: green;
height: 0%;/* right */
width: 32px;
z-index: 9999;
}
.box {
position: fixed;
top: 32.5px;
left: 32.5px;
background-color:white;
width: 100px;
height: 100px;
border: 1px solid black;
margin: auto;
z-index: 120;
margin: -10px -10px;
}
.wrap{
position: relative;
}
div.bottom {
position: absolute;
top: 123px;
background-color: green;
width: 0%; /* 27 = 100% */
height: 27px;
float: right;
right: 78vw;
z-index: 100;
}
div.left {
position: absolute;
background-color: white;
width: 23px;
height: 40%;
top: 23px;
bottom: 10px;
left: 0;
float: top;
}
div.noactive {
position: absolute;
background-color: white;
width: 23px;
height: 0%;
top: 23px;
bottom: 10px;
left: 0;
float: top;
}
.items {
margin-top: 50px;
text-align: center;
}
.grade,
.value {
height: 15px;
width: 50px;
align-items: center;
}
<div class='head'>
<div id='1' class='container'>
<div id='top' class='top'></div>
<div class='box'>
<h1 id='timer'>1</h1>
<div class='items'>
value<input id='grade' class='grade' type=number oninput="grade()"/>
range<input id='range' class='value' type=number oninput="grade()"/>
</div>
</div>
<div id='right' class='right'></div>
<div id='bottom' class='bottom'></div>
<div id='left' class='noactive'></div>
</div>
</div>
<script src='app.js'></script>

how to make an element stay in place when position changes from absolute to fixed

I have this button that on click reveals and expands a div element using a css transition, giving the illusion that the button itself expands. In order to have the div positioned on top of the button i set it to position: absolute but when open needs to be position: fixed. The problem i have with this is that when it switches between absolute to fixed it moves ruining the expantion effect. Here is the jsfiddle to my example.
function big() {
document.getElementById("content").classList.add('show');
document.getElementById("content").classList.add('bigger');
document.getElementById("content").classList.add('position');
}
function small() {
document.getElementById("content").classList.remove('bigger');
document.getElementById("content").classList.remove('position');
setTimeout(() => {
document.getElementById("content").classList.remove("show");
}, 1000);
document.getElementById("testo").classList.remove('show');
document.getElementById("close").classList.remove('show');
}
function delayed() {
setTimeout(function() {
document.getElementById("testo").classList.add('show');
}, 1100);
setTimeout(function() {
document.getElementById("close").classList.add('show');
}, 1100);
}
.button {
position: relative;
width: 100%;
height: 100%;
}
.button>button {
position: absolute;
left: 50vw;
top: 50vw;
color: white;
background-color: pink;
border: none;
padding: 30px;
cursor: pointer;
}
.button>button:hover {
background-color: purple;
}
.fixed {
position: absolute;
background-color: pink;
left: 50vw;
top: 50vw;
text-align: center;
width: 100px;
height: 75px;
transition: width 1s, height 1s, left 1s, top 1s, position 1s;
}
.position {
position: fixed;
}
.hidden {
visibility: hidden;
}
.show {
visibility: visible!important;
}
.bigger {
width: 100%;
height: 100%;
left: 0;
top: 0;
}
.close {
border: none;
visibility: hidden;
background-color: red;
position: absolute;
top: 5px;
right: 5px;
color: white;
cursor: pointer;
}
.close:hover {
background-color: yellow;
color: black;
}
#testo {
visibility: hidden;
}
body {
height: 1000px;
}
<div class="button">
<button onclick="big(); delayed()">expand</button>
<div id="content" class="fixed hidden">
<p id="testo">just testing this thing</p>
<button id="close" class="close" onclick="small()">X</button>
</div>
</div>
You can set an opacity or a transform: translate() on the .button parent container to make a fixed position child relative to the parent vs. the root of the document.
Doing this should give you the effect you're looking for.
function big() {
document.getElementById("content").classList.add('show');
document.getElementById("content").classList.add('bigger');
document.getElementById("content").classList.add('position');
}
function small() {
document.getElementById("content").classList.remove('bigger');
document.getElementById("content").classList.remove('position');
setTimeout(() => {
document.getElementById("content").classList.remove("show");
}, 1000);
document.getElementById("testo").classList.remove('show');
document.getElementById("close").classList.remove('show');
}
function delayed() {
setTimeout(function() {
document.getElementById("testo").classList.add('show');
}, 1100);
setTimeout(function() {
document.getElementById("close").classList.add('show');
}, 1100);
}
html,body {
width: 100%;
height: 100%;
}
.button {
position: relative;
/* opacity: 1; */
transform: translate(0, 0);
width: 100%;
height: 100%;
}
.button > button {
position: fixed;
left: 50%;
top: 50%;
color: white;
background-color: pink;
border: none;
padding: 30px;
cursor: pointer;
transform: translate(-50%, -50%);
}
.button > button:hover {
background-color: purple;
}
.fixed {
position: absolute;
background-color: pink;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
text-align: center;
width: 100px;
height: 75px;
transition: width 1s, height 1s, left 1s, top 1s, position 1s;
}
.position {
position: fixed;
}
.hidden {
visibility: hidden;
}
.show {
visibility: visible !important;
}
.bigger {
width: 100%;
height: 100%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.close {
border: none;
visibility: hidden;
background-color: red;
position: absolute;
top: 5px;
right: 5px;
color: white;
cursor: pointer;
}
.close:hover {
background-color: yellow;
color: black;
}
#testo {
visibility: hidden;
}
<div class="button">
<button onclick="big(); delayed()">expand</button>
<div id="content" class="fixed hidden">
<p id="testo">just testing this thing</p>
<button id="close" class="close" onclick="small()">X</button>
</div>
</div>
you can place fixed position to content after your animation is done
so your animation effect wont ruin . i have edited your fiddle see if this works as you like
edited fiddle
function big() {
document.getElementById("content").classList.add('show');
document.getElementById("content").classList.add('bigger');
setTimeout(function(){
document.getElementById("content").classList.add('position');
},1000)
}
function small() {
document.getElementById("content").classList.remove('bigger');
document.getElementById("content").classList.remove('position');
setTimeout(()=>{
document.getElementById("content").classList.remove("show");
}, 1000);
document.getElementById("testo").classList.remove('show');
document.getElementById("close").classList.remove('show');
}
function delayed() {
setTimeout(function(){document.getElementById("testo").classList.add('show');},1100);
setTimeout(function(){document.getElementById("close").classList.add('show');},1100);
}

Disable focused when hovering over other navbar items

I am strugglich with an issue, that my Navbar items get underline animation, when hovering over. Once clicked, animation stays there. However, if I hover over the neighbor navbar item, the two lines will appear next to each other, looking like one long line.
So here produkt is focused and preise is hovered. I wish, that when I hover over preise, the product gets unfocused. However, if I don't select preise, focus "returns back" to the product. Code below
.undeline:before {
content: '';
position: absolute;
width: 100%;
height: 3px;
bottom: 0;
left: 0;
background: #52ae49;
border-radius:3px;
margin-top: -10px;
visibility: hidden;
transform: scaleX(0);
transition: all 0.3s ease-in-out 0s;
}
.undeline:hover:before {
visibility: visible;
display: block;
transform: scaleX(1);
}
.undeline:focus:before {
content: '';
position: absolute;
width: 100%;
height: 3px;
bottom: 0;
left: 0;
background: #52ae49;
border-radius:3px;
margin-top: -10px;
visibility: visible;
display: block;
transform: scaleX(1);
}
I assume, I will have to manage this with JavaScript and use .forEach. I tried this
function mouseOver() {
$(".underline").each(function() {
$(this).blur('focus');
});
}
function mouseOut() {
$("underline").each(function() {
$(this).addClass('focus');
});
}
But with no success.
Here when you mean focus, i suppose you are talking about when you click the link. As focus is more suitable for html elements like input fields.
Please run the code snippet below to see it in action.
$('.nav li').on('click', function() {
var $link = $(this);
if (!$link.hasClass('selected')) {
$link.addClass('selected');
$link.siblings().removeClass('selected');
$link.siblings().removeClass('dimmed');
}
});
$('.nav li').hover(
// hover in handler
function() {
$(this).siblings('.selected').each(function() {
if (!$(this).hasClass('dimmed')) {
$(this).addClass('dimmed');
}
});
},
// hover out handler
function() {
$(this).siblings('.selected').each(function() {
$(this).removeClass('dimmed');
});
});
.nav {
display: flex;
}
.nav li {
position: relative;
list-style: none;
padding: 5px 10px;
text-transform: uppercase;
cursor: pointer;
}
li.selected.dimmed:before,
li:before {
content: '';
position: absolute;
width: 100%;
height: 3px;
bottom: 0;
left: 0;
background: #52ae49;
border-radius: 3px;
margin-top: -10px;
visibility: hidden;
transform: scaleX(0);
transition: all 0.3s ease-in-out 0s;
}
li:hover:before {
visibility: visible;
display: block;
transform: scaleX(1);
}
li.selected:before {
content: '';
position: absolute;
width: 100%;
height: 3px;
bottom: 0;
left: 0;
background: #52ae49;
border-radius: 3px;
margin-top: -10px;
visibility: visible;
display: block;
transform: scaleX(1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav">
<li>produkt</li>
<li>preise</li>
</div>

anchors overlaying and not properly changing color, because not fully clickable

I'm trying to change the color every image on click but they are not properly selectable because of overlying each other with positioning and z-index...
code is working as you can check by clicking on top right corner it change color...tried different methods of CSS, not JavaScript... newbie in JavaScript.
body,div,p,h1,h2,h3,h4,h5,h6,span {
margin: 0;
}
div.nav {
height: 100px;
width: 100%;
padding: 20px 0;
background-color: #615d5d;
text-align: center;
}
.screens_wrap {
display: inline-block;
margin: 0 auto;
height: 100%;
position: relative;
}
.screen_inner {
position: relative;
height: 100%;
margin: 0 auto;
width: 150px;
}
.screen {
position: absolute;
width:100px;
height: 58px;
border: 3px solid #aeaeae;
}
/* transparent style -------------------------------------------------------------------*/
.nav .screen.screen1 {
bottom: 0;
left: 0;
z-index: 3;
background-color: #00ad63;
}
.nav a .screen.screen2 {
bottom: 15px;
left: 15px;
z-index: 2;
background-color: transparent;
}
.nav a .screen.screen2:hover{
background-color: #4f025a;
}
.nav .screen.screen3 {
bottom: 30px;
left: 30px;
z-index: 1;
background-color: transparent;
}
.nav .screen.screen3:hover{
background-color: #ffec36;
}
.nav .screen2:hover, .screen3:hover {
-webkit-animation-name: hover;
-webkit-animation-duration: 1s;
animation-name: hover;
animation-duration: 4s;
-webkit-animation-fill-mode: forwards;
opacity: 1;
width: 100px;
}
.nav.nav6 {
height: 200px;
}
.screen_inner a.screenanchors:first-child img {
position: absolute;
left: 0;
top: 0;
z-index: 1;
}
.screen_inner a.screenanchors:nth-child(2) img{
position: absolute;
left: 20px;
top: 20px;
z-index: 2;
}
.screen_inner a.screenanchors:nth-child(3) img{
position: absolute;
left: 40px;
top: 40px;
z-index: 3;
}
.screenanchors img {
overflow: hidden;
}
#keyframes spinning {
from {
transform: translateZ(-5em) rotateY(0deg);
}
to {
transform: translateZ(-5em) rotateY(180deg);
}
}
#keyframes skewing {
from {
transform: translateZ(-5em) skew(-3deg, -25deg);
}
to {
transform: translateZ(-5em) skew(-3deg, 0deg);
width: 100%;
height: 100px;
z-index: 9999999;
bottom: 0;
}
}
/* Standard syntax */
#keyframes hover {
0% {
margin-bottom:+10px;
bottom: unset;
}
100% {
margin-bottom:+10px;
bottom: unset;
}
}
<div class="nav nav6" style="margin-top: 25px;">
<div class="screens_wrap">
<div class="screen_inner">
<img id="imgName" src="https://imageshack.com/i/plylrZh4p" onclick="changeSrc()" width="100px">
<img id="imgName1" src="https://imageshack.com/i/pljaZE0Gp" onclick="changeSrc1()" width="100px">
<img id="imgName2" src="https://imageshack.com/i/plm9slyTp" onclick="changeSrc2()" width="100px">
</div>
</div>
</div>
<script>
function changeSrc(){
document.getElementById("imgName").src="https://imageshack.com/i/plm9slyTp";
document.getElementById("imgName1").src="https://imageshack.com/i/plylrZh4p";
document.getElementById("imgName2").src="https://imageshack.com/i/pljaZE0Gp";
}
function changeSrc1(){
document.getElementById("imgName").src="https://imageshack.com/i/pljaZE0Gp";
document.getElementById("imgName1").src="https://imageshack.com/i/plm9slyTp";
document.getElementById("imgName2").src="https://imageshack.com/i/plylrZh4p";
}
function changeSrc2(){
document.getElementById("imgName").src="https://imageshack.com/i/plylrZh4p";
document.getElementById("imgName1").src="https://imageshack.com/i/pljaZE0Gp";
document.getElementById("imgName2").src="https://imageshack.com/i/plm9slyTp";
}
</script>
it should work by clicking every where on single image, no overlay effecting clickable space...
Just to Help out others, I fixed the issue using area mapping...

Javascript click and toggle class issue

I am just playing around trying to get a simple 3 slide slider working but run into some issues with the javascript. All i want to happen is on click of the slider colour i would like the current slider to slide out and the selected one to slide in. I am trying to do it by adding an active class to the slider number that I have clicked to show. I just cant quite work out where I have gone wrong. I don't want to use jQuery as I am trying to learn vanilla javascript.
Thanks as always
window.onload = onPageLoad();
function onPageLoad() {
document.querySelector('.red').classList.add('active');
};
document.querySelector('.box').addEventListener('click', function() {
document.querySelector('.red').classList.toggle('active');
document.querySelector('.green').classList.toggle('active');
document.querySelector('.yellow').classList.toggle('active');
});
* {
padding: 0;
margin: 0;
}
.main__wrapper {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
.red,
.green,
.yellow {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
transform: translateX(-100%);
transition: transform 1.2s;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.yellow {
background-color: yellow;
}
.active {
transform: translateX(0) !important;
transition: transform 1s !important;
}
.slide__select {
position: absolute;
bottom: 0;
right: 0;
width: 60%;
height: 20%;
z-index: 10;
display: flex;
}
.box {
position: relative;
flex: 1 0 0;
color: $color-white;
display: flex;
align-items: center;
cursor: pointer;
background-color: #A68D71;
}
.box span {
display: block;
position: relative;
z-index: 11;
}
.box::after {
content: "";
position: absolute;
top: 0;
left: 0;
background-color: yellow;
width: 100%;
height: 0;
transition: height .3s;
}
.box:hover::after {
height: 100%;
transition: height .3s;
}
<div class="main__wrapper">
<section class="red">
</section>
<section class="green">
</section>
<section class="yellow">
</section>
<div class="slide__select">
<div class="box">
<span>red</span>
</div>
<div class="box">
<span>green</span>
</div>
<div class="box">
<span>yellow</span>
</div>
</div>
</div>
You're only adding an event listener to the first box and you're toggling every box's active class in order, and the last one is yellow, so you result with a yellow background.
querySelector returns the first DOM element it finds, which is the red box.
For the functionality that you want, you have to add event listeners to each box (querySelectorAll)
window.onload = onPageLoad();
function onPageLoad() {
document.querySelector('.red').classList.add('active');
};
document.querySelector('.redbox').addEventListener('click', function() {
document.querySelector('.red').classList.add('active');
document.querySelector('.green').classList.remove('active');
document.querySelector('.yellow').classList.remove('active');
});
document.querySelector('.greenbox').addEventListener('click', function() {
document.querySelector('.red').classList.remove('active');
document.querySelector('.green').classList.add('active');
document.querySelector('.yellow').classList.remove('active');
});
document.querySelector('.yellowbox').addEventListener('click', function() {
document.querySelector('.red').classList.remove('active');
document.querySelector('.green').classList.remove('active');
document.querySelector('.yellow').classList.add('active');
});
* {
padding: 0;
margin: 0;
}
.main__wrapper {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
.red,
.green,
.yellow {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
transform: translateX(-100%);
transition: transform 1.2s;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.yellow {
background-color: yellow;
}
.active {
transform: translateX(0) !important;
transition: transform 1s !important;
}
.slide__select {
position: absolute;
bottom: 0;
right: 0;
width: 60%;
height: 20%;
z-index: 10;
display: flex;
}
.box {
position: relative;
flex: 1 0 0;
color: $color-white;
display: flex;
align-items: center;
cursor: pointer;
background-color: #A68D71;
}
.box span {
display: block;
position: relative;
z-index: 11;
}
.box::after {
content: "";
position: absolute;
top: 0;
left: 0;
background-color: yellow;
width: 100%;
height: 0;
transition: height .3s;
}
.box:hover::after {
height: 100%;
transition: height .3s;
}
<div class="main__wrapper">
<section class="red">
</section>
<section class="green">
</section>
<section class="yellow">
</section>
<div class="slide__select">
<div class="redbox box">
<span>red</span>
</div>
<div class="greenbox box">
<span>green</span>
</div>
<div class="yellowbox box">
<span>yellow</span>
</div>
</div>
</div>
Here is a primitive example solution. It's overly verbose but shows you what is needed. This can be condensed.
To get an idea of how it can be condensed, all three listeners CAN be condensed into a single listener how you had it, listen just to the .box selector. But if you do that, you need a way to identify which box was clicked. This can be done via a data attribute or by looking at the html text. A data attribute would be my preferred method, as it separates the content from the logic a bit, but either would work.
Another less verbose solution:
window.onload = onPageLoad();
function onPageLoad() {
document.querySelector('.red').classList.add('active');
};
var boxes = document.querySelectorAll('.box');
for (var i = 0; i < boxes.length; i++) {
boxes[i].addEventListener('click', toggleSections);
}
var colors = ['red', 'green', 'yellow'];
function toggleSections(ev) {
var color = ev.currentTarget.innerText;
for (var c = 0; c < colors.length; c++) {
var colorElem = document.querySelector('.' + colors[c]);
if (colors[c] != color) {
colorElem.classList.remove('active');
} else {
colorElem.classList.add('active');
}
}
}
* {
padding: 0;
margin: 0;
}
.main__wrapper {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
.red,
.green,
.yellow {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
transform: translateX(-100%);
transition: transform 1.2s;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.yellow {
background-color: yellow;
}
.active {
transform: translateX(0) !important;
transition: transform 1s !important;
}
.slide__select {
position: absolute;
bottom: 0;
right: 0;
width: 60%;
height: 20%;
z-index: 10;
display: flex;
}
.box {
position: relative;
flex: 1 0 0;
color: $color-white;
display: flex;
align-items: center;
cursor: pointer;
background-color: #A68D71;
}
.box span {
display: block;
position: relative;
z-index: 11;
}
.box::after {
content: "";
position: absolute;
top: 0;
left: 0;
background-color: yellow;
width: 100%;
height: 0;
transition: height .3s;
}
.box:hover::after {
height: 100%;
transition: height .3s;
}
<div class="main__wrapper">
<section class="red">
</section>
<section class="green">
</section>
<section class="yellow">
</section>
<div class="slide__select">
<div class="box">
<span>red</span>
</div>
<div class="box">
<span>green</span>
</div>
<div class="box">
<span>yellow</span>
</div>
</div>
</div>
To achieve expected result, use below option
Use one section to avoid looping of section elements
Use querySelectorAll or elementsByClassName instead of querySelector to fetch all elements in array
Use forEach to loop through all elements of class- box and add addEventListener and run another loop with forEach for span elements
Use classList to add or remove
window.onload = onPageLoad();
function onPageLoad() {
document.querySelector('.red').classList.add('active');
};
// use querySelectorAll to get all elements of class-box and forEach to loop through
document.querySelectorAll('.box').forEach(function(ele){
//Add clici event through addEventListener
ele.addEventListener('click', function() {
// use another querySelectorAll to get all elements of tag span and forEach to loop through
document.querySelectorAll('span').forEach(function(e){
e.classList.remove('active');
//use querySelector for section element and empty classList to remove active and red/green/yellow class names
document.querySelector('section').className ='';
});
//toggle active class for clicked element
ele.children[0].classList.toggle("active");
//add active class for section
document.querySelector('section').classList.add('active');
//add class red/yellow/green using span innerHTML
document.querySelector('section').classList.add(ele.children[0].innerHTML);
});
});
* {
padding: 0;
margin: 0;
}
.main__wrapper {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
.red,
.green,
.yellow {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
transform: translateX(-100%);
transition: transform 1.2s;
}
.red {
background-color: red;
}
.green {
background-color: green;
}
.yellow {
background-color: yellow;
}
.active {
transform: translateX(0) !important;
transition: transform 1s !important;
}
.slide__select {
position: absolute;
bottom: 0;
right: 0;
width: 60%;
height: 20%;
z-index: 10;
display: flex;
}
.box {
position: relative;
flex: 1 0 0;
color: $color-white;
display: flex;
align-items: center;
cursor: pointer;
background-color: #A68D71;
}
.box span {
display: block;
position: relative;
z-index: 11;
}
.box::after {
content: "";
position: absolute;
top: 0;
left: 0;
background-color: yellow;
width: 100%;
height: 0;
transition: height .3s;
}
.box:hover::after {
height: 100%;
transition: height .3s;
}
<div class="main__wrapper">
<section class="red">
</section>
<div class="slide__select">
<div class="box">
<span>red</span>
</div>
<div class="box">
<span>green</span>
</div>
<div class="box">
<span>yellow</span>
</div>
</div>
</div>
code sample - https://codepen.io/nagasai/pen/vRoPwp

Categories