I have 5 blank boxes, and I would like each of them to be filled up in order every 1 second. How do I do this? My JS is wrong and not working.
let blankSquare = document.querySelectorAll(".square");
function fillUp() {
setInterval(() => {
blankSquare.classList.add(".fill")
}, 1000)
}
blankSquare.addEventListener("fillUp");
.square {
margin: 1vh;
height: 3vh;
width: 3vh;
background-color: none;
border: solid 2px grey;
}
.fill {
background-color: grey;
}
<div >
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
</div>
CodePudding user response:
Staggered animation using CSS
Here's an example where you don't necessarily need JavaScript, but simply a style
attribute containing a CSS var (variable) like style="--anim=N"
where N
is an index from 0
to N
, and use CSS calc()
for the animation-delay
property:
.square {
height: 3vh;
aspect-ratio: 1;
border: solid 2px grey;
animation: fill 0.3s calc(var(--anim) * 1s) forwards;
}
@keyframes fill {
to { background: grey; }
}
<div >
<div style="--anim:0"></div>
<div style="--anim:1"></div>
<div style="--anim:2"></div>
<div style="--anim:3"></div>
<div style="--anim:4"></div>
</div>
If you don't want to hardcode manually the style
attribute, simply add this JS:
const ELS = (sel, el) => (el || document).querySelectorAll(sel);
ELS(".square").forEach((el, i) => el.style.setProperty("--anim", i));
Staggered animation using JavaScript
Given a function in JavaScript with which you can decide when to start your staggered animation:
Use setTimeout
instead of setInterval
inside a recursive
fillUp
function which accepts as arguments 1: a collection of elements, 2: a start index.
An incremented index is passed for every next recursive function call
const fillUp = (els, i = 0) => {
els[i].classList.add("fill");
i = 1;
if (i < els.length) setTimeout(() => fillUp(els, i), 1000);
};
fillUp(document.querySelectorAll(".square"));
.square {
height: 3vh;
aspect-ratio: 1;
border: solid 2px grey;
}
.fill {
background-color: grey;
}
<div >
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
</div>
Related articles / resources:
CodePudding user response:
You can store the index of the item in a variable, and increment it inside the interval.
let blankSquare = document.querySelectorAll(".square");
let index = 0;
function fillUp() {
setInterval(() => {
blankSquare[index ].classList.add("fill")
}, 1000)
}
fillUp()
.square {
margin: 1vh;
height: 3vh;
width: 3vh;
background-color: none;
border: solid 2px grey;
}
.fill {
background-color: grey;
}
<div >
<div ></div>
<div ></div>
<div ></div>
<div ></div>
<div ></div>
</div>