CSS3 transition events

145,348

Solution 1

W3C CSS Transitions Draft

The completion of a CSS Transition generates a corresponding DOM Event. An event is fired for each property that undergoes a transition. This allows a content developer to perform actions that synchronize with the completion of a transition.


Webkit

To determine when a transition completes, set a JavaScript event listener function for the DOM event that is sent at the end of a transition. The event is an instance of WebKitTransitionEvent, and its type is webkitTransitionEnd.

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

Mozilla

There is a single event that is fired when transitions complete. In Firefox, the event is transitionend, in Opera, oTransitionEnd, and in WebKit it is webkitTransitionEnd.

Opera

There is one type of transition event available. The oTransitionEnd event occurs at the completion of the transition.

Internet Explorer

The transitionend event occurs at the completion of the transition. If the transition is removed before completion, the event will not fire.


Stack Overflow: How do I normalize CSS3 Transition functions across browsers?

Solution 2

Update

All modern browsers now support the unprefixed event:

element.addEventListener('transitionend', callback, false);

https://caniuse.com/#feat=css-transitions


I was using the approach given by Pete, however I have now started using the following

$(".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 (  ._.)
  }


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

}(jQuery);

Note they also include an emulateTransitionEnd function which may be needed to ensure a callback always occurs.

  // 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
  }

Be aware that sometimes this event doesn’t fire, usually in the case when properties don’t change or a paint isn’t triggered. To ensure we always get a callback, let’s set a timeout that’ll trigger the event manually.

http://blog.alexmaccaw.com/css-transitions

Solution 3

All modern browsers now support the unprefixed event:

element.addEventListener('transitionend', callback, false);

Works in the latest versions of Chrome, Firefox and Safari. Even IE10+.

Solution 4

In Opera 12 when you bind using the plain JavaScript, 'oTransitionEnd' will work:

document.addEventListener("oTransitionEnd", function(){
    alert("Transition Ended");
});

however if you bind through jQuery, you need to use 'otransitionend'

$(document).bind("otransitionend", function(){
    alert("Transition Ended");
});

In case you are using Modernizr or bootstrap-transition.js you can simply do a change:

var transEndEventNames = {
    'WebkitTransition' : 'webkitTransitionEnd',
    'MozTransition'    : 'transitionend',
    'OTransition'      : 'oTransitionEnd otransitionend',
    'msTransition'     : 'MSTransitionEnd',
    'transition'       : 'transitionend'
},
transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];

You can find some info here as well http://www.ianlunn.co.uk/blog/articles/opera-12-otransitionend-bugs-and-workarounds/

Solution 5

Just for fun, don't do this!

$.fn.transitiondone = function () {
  return this.each(function () {
    var $this = $(this);
    setTimeout(function () {
      $this.trigger('transitiondone');
    }, (parseFloat($this.css('transitionDelay')) + parseFloat($this.css('transitionDuration'))) * 1000);
  });
};


$('div').on('mousedown', function (e) {
  $(this).addClass('bounce').transitiondone();
});

$('div').on('transitiondone', function () {
  $(this).removeClass('bounce');
});
Share:
145,348

Related videos on Youtube

Andreas Köberle
Author by

Andreas Köberle

Updated on January 06, 2021

Comments

  • Andreas Köberle
    Andreas Köberle over 3 years

    Are there any events fired by an element to check whether a css3 transition has started or end?

  • Andreas Köberle
    Andreas Köberle almost 14 years
    Note that the event is called "transitionend" in firefox and "oTransitionEnd" in Opera
  • tyler
    tyler over 12 years
    No one has mentioned anything about the transition-start part of the question. Is there no way to register an event handler to be fired before the transition begins?
  • Mild Fuzz
    Mild Fuzz almost 12 years
    Is there now a standard way of achieving this? Seems 2 years is a long time! Things have likely changed.
  • Davor Lucic
    Davor Lucic almost 12 years
    @tyler i don't know how to work around the lack of transitions-start.
  • Davor Lucic
    Davor Lucic almost 12 years
    @Mild Fuzz linked stackoverflow question has interesting solution.
  • Chris Love
    Chris Love over 11 years
    looks like IE supports transitionend github.com/twitter/bootstrap/pull/4109
  • sebastian
    sebastian almost 11 years
    You can't do something like that. In some cases callbaack will be fired more than once.
  • AlexG
    AlexG over 10 years
    In browsers that keep both the prefixed and the regular event names around. You can workaround it by using .one instead of .on
  • Jesse
    Jesse over 3 years
    Just fyi: The first solution looks nice and handy but it causes a memory leak: codepen.io/jjd/pen/ZEpGGqG To avoid that, namespace all of the event names and explicitly deregister them. Otherwise you end up adding a bunch of event listeners, each time the code is executed and those are never cleaned up. $(".myClass").one('transitionend.namespace webkitTransitionEnd.namespace oTransitionEnd.namespace otransitionend.namespace MSTransitionEnd.namespace', function() { $(this).off('.namespace'); //do something });