I have the following code and my problem is that the transitionend
event is fired twice. I don\'t know what\'s causing this. I suspected the vendor prefixes cau
For anyone still looking for a more robust solution, like "allTransitionEnd" event, I've implemented a jQuery "special event", more as a proof of concept for something I was working on, but I might put out a lib on Github.
Check out the JSBin.
It's quite tricky, so I won't explain too much, but it makes it real easy to do stuff after ALL transitions have ended on an element:
$(function () {
$element.on('allTransitionEnd', function () {
// do something after all transitions end.
});
});
It works by probing the element for transition properties, then binds to the native transitionend
events (vendor specific included) in order to keep track of properties that have finished transitioning. When all have finished transitioning it triggers any bound allTransitionsEnd
handlers and then clears transition properties, in case they've changed as well, and probes for them fresh next time around.
This is really useful when multiple properties are being transitioned with varying delay and/or duration and you want to do something after all transitions have completed.
Example use cases:
If you are only transitioning one property, or have no varied delays and/or durations, then a simple solution works fine.
Works in latest version of Chrome, Firefox, Safari, Mobile Safari and IE11 and IE10. Doesn't work in IE8 because transitions are not supported. Bind to an additional native event as fallback.
transitionend
fires for each property transitioned, in your case top
and left
.
You can access the property associated with the event at event.propertyName
.
There's no "transitionsend" event, so you will probably need some hackiness such as filtering the transitionend
callback handling for only one of the transitioned properties. E.g.:
function (event) {
if (event.propertyName == 'top') {
//put your code here
}
});
ps. No browser fires the MSTransitionEnd
event. It was at some point in the MS docs, but sometime before the IE10 beta release it was replaced by the standard transitionend
event.
This is a relatively old question but I thought I'd share my answer:
function OnTransitionEvent() {
var t,
el = document.createElement('transitionElement');
var transitions = {
'transition' : 'transitionend',
'OTransition' : 'oTransitionEnd',
'MozTransition' : 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
};
for (t in transitions){
if (el.style[t] !== undefined){
return transitions[t];
}
}
}
var transitionEvent = OnTransitionEvent();
$(document).one(transitionEvent, function() {
console.log('done');
});
For anyone looking for a simple, one time copy and paste solution (I've only included the necessary css). This doesn't answer the question and it does answer what I was looking for when I landed here.
CSS:
.my-elem {
transition: height 0.5s ease-out, opacity 0.5s ease-out;
}
JavaScript:
var elem = document.querySelector(".my-elem");
var transitionCounter = 0;
var transitionProp = window.getComputedStyle(elem , null)["transition-property"] || "";
// We just need to know how many transitions there are
var numTransitionProps = transitionProp.split(",").length;
elem.addEventListener("transitionend", (event) => {
// You could read event.propertyName to find out which transition was ended,
// but it's not necessary if you just want to know when they are all done.
if (transitionCounter < (numTransitionProps - 1)) {
transitionCounter++;
} else {
transitionCounter = 0; // reset
alert("I'm done!!!"); // do what you need to
}
}, false);
Tested in IE11, Chrome 48 and Firefox 37.
You can use the target
property to filter out events that are triggered by child elements and use propertyName
to only trigger the event when a specific property changed.
const handleTransitionEnd = event => {
if (event.target !== myDomElementRef) return;
if (event.propertyName !== "height") return;
// Do my things
};
The event fires for each property that has been transitioned.
The propertyName
way that Fabricio suggested is the proper way to do this, however depending on the circumstances you can also use one();
as well, like this.
$(document).one('transitionend webkitTransitionEnd MSTransitionEnd', function() {
...
});