108

Is it possible to get a notification (like callback) when a CSS transition has been completed?

1

5 Answers 5

109

Yes, if such things are supported by the browser, then an event is triggered when the transition completes. The actual event however, differs between browsers:

  • Webkit browsers (Chrome, Safari) use webkitTransitionEnd
  • Firefox uses transitionend
  • IE9+ uses msTransitionEnd
  • Opera uses oTransitionEnd

However you should be aware that webkitTransitionEnd doesn't always fire! This has caught me out a number of times, and seems to occur if the animation would have no effect on the element. To get around this, it makes sense to use a timeout to fire the event handler in the case that it's not been triggered as expected. A blog post about this problem is available here: http://www.cuppadev.co.uk/the-trouble-with-css-transitions/ <-- 500 Internal Server Error

With this in mind, I tend to use this event in a chunk of code that looks a bit like this:

var transitionEndEventName = "XXX"; //figure out, e.g. "webkitTransitionEnd".. 
var elemToAnimate = ... //the thing you want to animate..
var done = false;
var transitionEnded = function(){
     done = true;
     //do your transition finished stuff..
     elemToAnimate.removeEventListener(transitionEndEventName,
                                        transitionEnded, false);
};
elemToAnimate.addEventListener(transitionEndEventName,
                                transitionEnded, false);

//animation triggering code here..

//ensure tidy up if event doesn't fire..
setTimeout(function(){
    if(!done){
        console.log("timeout needed to call transition ended..");
        transitionEnded();
    }
}, XXX); //note: XXX should be the time required for the
        //animation to complete plus a grace period (e.g. 10ms) 

Note: to get the transition event end name you can use the method posted as the answer in: How do I normalize CSS3 Transition functions across browsers?.

Note: this question is also related to: - CSS3 transition events

Sign up to request clarification or add additional context in comments.

5 Comments

This is a much fuller answer than the accepted one. Why isn't this more upvoted.
Remember to call transitionEndedHandler in transitionEnded (or change transitionEnded by transitionEndedHandler in addEventListener and removeEventListener and call transitionEnded in transitionEndedHandler)
Thanks @Miquel; think I'd just used transitionEnded when I meant transitionEndedHandler.
I believe the Chromium issue for this can be found here: code.google.com/p/chromium/issues/detail?id=388082 Although, the last comment seems to (incorrectly in my view) discount it as a bug and therefore it is currently marked as "won't fix".
No need for different names nowadays caniuse.com/#feat=css-transitions
83

I know that Safari implements a webkitTransitionEnd callback that you can attach directly to the element with the transition.

Their example (reformatted to multiple lines):

box.addEventListener( 
     'webkitTransitionEnd', 
     function( event ) { 
         alert( "Finished transition!" ); 
     }, false );

6 Comments

is there the same thing for other browser then webkit?
yes, 'transitionend' for Mozilla & 'oTransitionEnd' in Opera.
what does the false at the end do?
@meo It has something to do with the this element inside the callback. But its a required parameter, so in this case its just fulfilling the requirement.
@DougNeiner The false at the end is for useCaptureMode. When an event occurs, there are two phases - the first phase is capture mode, the second is bubble mode. In capture mode, the event descends from the body element to the specified element. It then enters bubble mode, where it does the reverse. That final false param specifies that you want the event listener to occur in bubble mode. One use of this is to attach event handlers right before they are needed in bubble mode. =) 37signals.com/svn/posts/…
|
44

I am using the following code, is much simpler than trying to detect which specific end event a browser uses.

$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', 
function() {
 //do something
});

Alternatively if you use bootstrap then you can simply do

$(".myClass").one($.support.transition.end,
function() {
 //do something
});

This is becuase they include the following in bootstrap.js

+function ($) {
  'use strict';

  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  // ============================================================

  function transitionEnd() {
    var el = document.createElement('bootstrap')

    var transEndEventNames = {
      'WebkitTransition' : 'webkitTransitionEnd',
      'MozTransition'    : 'transitionend',
      'OTransition'      : 'oTransitionEnd otransitionend',
      'transition'       : 'transitionend'
    }

    for (var name in transEndEventNames) {
      if (el.style[name] !== undefined) {
        return { end: transEndEventNames[name] }
      }
    }

    return false // explicit for ie8 (  ._.)
  }

  // http://blog.alexmaccaw.com/css-transitions
  $.fn.emulateTransitionEnd = function (duration) {
    var called = false, $el = this
    $(this).one($.support.transition.end, function () { called = true })
    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
    setTimeout(callback, duration)
    return this
  }

  $(function () {
    $.support.transition = transitionEnd()
  })

}(jQuery);

2 Comments

This is slower because it has to search through that entire list each time the event happens to see if it is the correct one.
@phreakhead The performances of any of these approaches will be very similar
12

This can easily be achieved with the transitionend event. See documentation here.

A simple example:

document.getElementById("button").addEventListener("transitionend", myEndFunction);

function myEndFunction() {
    this.innerHTML = "Transition event ended";
}
#button {transition: top 2s; position: relative; top: 0;}
<button id="button" onclick="this.style.top = '55px';">Click me to start animation</button>

2 Comments

This is the correct answer nowadays, there's no need to have prefixes anymore. caniuse.com/#feat=css-transitions
6

The jQuery.transit plugin, a plugin for CSS3 transformations and transitions, can call your CSS animations from script and give you a callback.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.