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.

References