I ran into a little issue when I was doing a challenge, making a game with just HTML elements (not including canvas), css, and js. When something dies its supposed to play a death animation then another different animation. The first animation fires but the second one does not. I wrote some pseudo code below that demonstrates my problem.
JSFiddle: https://jsfiddle.net/ds908ah1/
let element = document.getElementById("text");
element.classList.add("popIn");
setTimeout(()=>{
element.classList.remove("popIn");
element.classList.add("popOut");
}, 500/*anim length*/);
@keyframes anim{
from{
opacity: 0;
transform: scale(0);
}
to{
opacity: 1;
transform: scale(1);
}
}
.popIn, .popOut{
animation-duration: 0.5s;
animation-name: anim;
animation-timing-function: cubic-bezier(0.6, 1.5, 0.64, 1);
}
.popOut{
animation-direction: reverse;
}
<p id="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eget dui egestas, pretium purus non, ultricies ligula. Fusce ultricies congue nisi ut congue. Praesent euismod, massa vitae consequat dictum, enim lacus finibus tortor, eget auctor felis nisi ut enim. Aliquam vitae sapien lorem. Phasellus ac dolor ac leo pellentesque ornare. Mauris in sem vestibulum, elementum augue sit amet, ultricies purus. Aenean id justo nunc. Mauris sit amet eros pretium, commodo ex vitae, pellentesque odio. Vivamus vel nunc sit amet tellus lobortis viverra. Donec consequat massa urna, in maximus justo placerat sit amet. Etiam non dui in est lobortis vulputate.
</p>
CodePudding user response:
Due to performance concerns, browsers typically do not recalculate the layout of a webpage until a reflow event is called.
To fix this, simply call an event which can trigger a reflow. For example,
let element = document.getElementById("text");
element.classList.add("popIn");
setTimeout(()=>{
element.classList.remove("popIn");
element.offsetHeight;
element.classList.add("popOut");
}, 500/*anim length*/);
@keyframes anim{
from{
opacity: 0;
transform: scale(0);
}
to{
opacity: 1;
transform: scale(1);
}
}
.popIn, .popOut{
animation-duration: 0.5s;
animation-name: anim;
animation-timing-function: cubic-bezier(0.6, 1.5, 0.64, 1);
}
.popOut{
animation-direction: reverse;
}
<p id="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc eget dui egestas, pretium purus non, ultricies ligula. Fusce ultricies congue nisi ut congue. Praesent euismod, massa vitae consequat dictum, enim lacus finibus tortor, eget auctor felis nisi ut enim. Aliquam vitae sapien lorem. Phasellus ac dolor ac leo pellentesque ornare. Mauris in sem vestibulum, elementum augue sit amet, ultricies purus. Aenean id justo nunc. Mauris sit amet eros pretium, commodo ex vitae, pellentesque odio. Vivamus vel nunc sit amet tellus lobortis viverra. Donec consequat massa urna, in maximus justo placerat sit amet. Etiam non dui in est lobortis vulputate.
</p>
The addition of element.offsetHeight
causes the browser to recalculate DOM Reflow which allows for a change in animation.
You can check out https://betterprogramming.pub/how-to-restart-a-css-animation-with-javascript-and-what-is-the-dom-reflow-a86e8b6df00f for more information regarding this topic.