CSS animations give us a quick easy way to animate things. By combining them with JavaScript it will give us the control to take the animation to a new level.
For instance, because CSS animations comes with the animationend
event we can use that with JavaScript to check whether the animation has ended or is still running. This is useful for more complex animations where you want to do something after or based on what state the animation is in.
Animation Event Listeners
There are three CSS Animation events. We'll use the animationend
event with JavaScript to listen for the previous animation to end and then run the next one. We can call it when the document is first loaded with an addEventListener
function.
el.addEventListener("animationstart", function() {}, false);
el.addEventListener("animationend", function() {}, false);
el.addEventListener("animationiteration", function() {}, false);
In this example we have a series of animation events and after each event has ended we want to run the next animation.
<div id="bars">
<div class="bar one"></div>
<div class="bar two"></div>
<div class="bar two"></div>
</div>
Well use @keyframes
and animation
properties to run the width and set the duration.
.run {
height: 40px;
background: grey;
animation: bars 1s;
margin-bottom: 12px;
}
@keyframes bars {
from {
width: 0;
}
to {
width: 100%;
}
}
First we get the parent div Id then use the children
property to return a live HTMLCollection which contains all of the child elements. Now that we have all the child elements we can turn that NodeList into an array so it can be looped through. So if we console.log(childArray)
we get each of the child div's that we need.
Then were going to use a forEach
loop to loop over each of the children and remove the run class so we can start a fresh new animation.
We need to run the first child by getting the 0 index of the array and add the run class to that div. Now we will have access to the CSS animationend
event that gets fired when a CSS Animation has completed. This will give us a baseline to iterate from and fire the rest of the animations.
Then we run another forEach
loop to add the run class for the rest of the animations. I put this in a setTimeout
function that adds a delay between each of the animations and gives it a transition. The real magic happens here with the addEventListener
property that listens for the animationend
event and uses the nextElementSibling
property to get the the next child that will get the run class add to it.
const bars = document.getElementById('bars');
let children = bars.children;
let childArray = [...children];
childArray.forEach(function(childBar) {
childBar.classList.remove("run");
//console.log(childBar);
})
setTimeout(() => {
childArray[0].classList.add("run");
childArray.forEach(function(child) {
child.addEventListener("animationend", function() {
if (this.nextElementSibling) {
this.nextElementSibling.classList.add("run");
}
});
});
}, 100)
Example
I'm sure there many ways to customize this method for different types of projects. The main idea is mixing CSS Animation and JavaScript to create animations that can take your user experience to the next level.