animationend event not firing
There are two separate animating events.
- animationend
- transitionend
When using the css transition
use transitionend
, and when using @keyframes/animation
, use animationend
.
Animationend event not firing on :after element
After searching the web it has become apparent that IE does not yet support the binding to animation events on a pseudo element. This is made more obvious by the jsFiddle I posted in my original post, which doesn't trigger the event when the animation ends.
animationend event also also fires on end of animations of child elements?
You can check if the event's target is the element the listener is attached to. The event handler is also called when the animation on a child element ends because the animationend
event bubbles.
document.querySelector('.outer').addEventListener('animationend', function(e) {
if(e.target === this) console.log('done')
})
document.querySelector('.outer').addEventListener('animationend',function (e) {
if(e.target === this) console.log('done')
})
body {
height:100vh;
display:grid;
place-items:center;
}
.outer {
display:grid;
place-items:center;
height:200px;
width:200px;
background:black;
animation:spin 2s
}
.inner {
height:50px;
width:50px;
background:red;
animation:spin 2s 2s
}
@keyframes spin {
from {
transform:rotate(0)
}
to {
transform:rotate(360deg)
}
}
<div class="outer">
<div class="inner">
</div>
</div>
addEventListener not firing when animation ends
Put your multiple event types in an array the use .forEach()
method.
SNIPPET
var div = document.querySelector('.animated');
['webkitAnimationEnd', 'animationend'].forEach(function(e) { div.addEventListener(e, eventHandler, false);});
function eventHandler(e) { var tgt = e.target; tgt.style.color = 'red';}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
<div class="animated tada">TADA!</div>
Detect element CSS animation end, child items firing the event
animationend
bubbles, so animations on descendant elements bubble up to the parent.
If you only want to handle the event when it relates specifically to elm
(this.$refs.container
), compare event.target
to elm
(or event.currentTarget
) and ignore the event if they don't match:
elm.addEventListener('transitionend', event => {
if (event.target !== event.currentTarget) {
return; // Ignore it
}
console.log(event.target);
});
Updated Example (I've added a border to the container so you can see the animation occur and see that the console.log
happens when it ends):
Vue.component('test', {
data: function () {
return {
count: 0
}
},
methods: {
expand() {
const elm = this.$refs.container;
elm.addEventListener('transitionend', event => {
if (event.target !== event.currentTarget) {
return; // Ignore it
}
console.log(event.target);
});
elm.style.height = '100px';
}
},
template: `
<div>
<p @click="expand()">Expand</p>
<div class="container"
ref="container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
</div>
</div>
`
})
new Vue().$mount('#app');
.container {
transition: height .3s ease;
height: 0;
border: 1px solid grey;
}
.container ul li:hover {
background: red;
}
.container ul li {
transition: background .2s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<test></test>
</div>
How to fire animationend event, when I can't set a CSS animation?
You can check if element.style.WebkitAnimation
and element.style.animation
contain any value and execute run()
if the value is ""
Edit Turns out that .style
will return "" for any value. What you need is window.getComputedStyle()
along with the property animationName
. If it is none
, there is no animation, else there is. Check the code below:
var el1 = document.getElementById("notAnimation");console.log(window.getComputedStyle(el1)["animationName"])
var el2 = document.getElementById("onAnimation");console.log(window.getComputedStyle(el2)["animationName"])
div { padding: 10px; margin: 20px;}
#notAnimation {}
#onAnimation { animation: scale 10s ease-in-out;}
@keyframes scale { 0% { transform: scale(1); opacity: 1; color: black; } 50% { transform: scale(0.95); opacity: .4; color: red; } 100% { transform: scale(1); opacity: 1; color: black; }}
<div id="notAnimation"> Not Animation</div>
<div id="onAnimation"> Animation</div>
JS EventListener animationend firing too early
Your issue is in your addEventListener:
element.addEventListener("webkitAnimationEnd", element.classList.remove("smoothTransition"));
element.addEventListener("animationend", element.classList.remove("smoothTransition"));
The second argument of addEventListener must be a a function and not the result of a function call (in your case undefined). Hence, change the previous lines to:
element.addEventListener("webkitAnimationEnd", function(e) {
this.classList.remove("smoothTransition")
});
element.addEventListener("animationend", function(e) {
this.classList.remove("smoothTransition")
});
You may consider to add your event listeners before transitions.
document.addEventListener("DOMContentLoaded", function(e) { var element = document.querySelector('.box'); element.addEventListener("webkitAnimationEnd", function(e) { this.classList.remove("smoothTransition"); console.log('webkitAnimationEnd'); }); element.addEventListener("animationend", function(e) { this.classList.remove("smoothTransition"); console.log('animationend'); }); element.classList.add("smoothTransition") element.classList.toggle("fullscreen")});
.box { width: 150px; height: 150px; background: red; margin-top: 20px; margin-left: auto; margin-right: auto;}@keyframes colorchange { 0% { background: yellow } 100% { background: blue }}.smoothTransition { animation: colorchange 2s;}.fullscreen { width: 100%; height: 100vh;}
<div class="box"></div>
Related Topics
Is It Better to Use Jquery Fadein or CSS3 Animations
Changing Background Color of a Specific Row in Slickgrid
Image Reflection Effect Using Pure CSS
Vertical-Align Text Within a Textarea
Onclick Show Div, But Hide When Other One Is Clicked
Browser Support for Angular Material
Flexslider <Li> Height's Equal the Tallest <Li> on a Mobile Browser
How to Set the Margin of an Object in Ie
How to Click on Hidden Element in Protractor
Adding Style Stored in a Variable Inside React Class
How to Have HTML-Webpack-Plugin Generate <Style> Elements from CSS
Mui Button Hover Background Color and Text Color
How to Scroll to Top on Route Change with React Router Dom V6
How to Save an Image with CSS Filter Applied