LearnUsing jQuery to Detect When CSS3 Animations and Transitions End

Louis Lazaris
writes on January 14, 2013

Share with your friends










Submit

It seems like only a couple of years ago that almost every animation on a web page was done either by means of Flash or a JavaScript library like jQuery.

CSS3 has put that to rest. Simple, elegant animations are possible using CSS3 transitions, and even complex fine-grained movement can be accomplished using CSS3 keyframe animations. And now that every major modern browser supports both transitions and keyframe animations, they are a very real possibility on every new project we create.

In this post, I’ll discuss how you can include callback-like behaviour when using CSS3 transitions and animations, and thus keep your animation effects separate from your jQuery logic.

Separating Logic from Effect

How do we apply a principle like “separation of concerns” when implementing both JavaScript and CSS3? Although no solution works in every circumstance (i.e. the “it depends” adage applies here), I do believe we can lay down some practical guidelines in this area.

My advice up front in this post is: Use JavaScript for logic, functionality, and event firing, and use CSS3 for creating the effects (i.e. animations and/or transitions) that the JavaScript triggers.

In the past, when CSS3 animations weren’t an option, we would see jQuery code that resembled this:

$('#button').click(function () { 

    $('.box').animate({
        height: '300px',
        width: '200px'
    }, 3000);

});

A pretty bare-bones example, but it demonstrates the need for separation. The click event is indeed handled by the JavaScript, but we also have an animation with hard-coded CSS values in the JavaScript.

CSS3, however, lets us separate the functionality from the animation, so now our JavaScript might look like this:

$('#button').click(function () { 

    $('.box').toggleClass('change-size');

});

And here’s our associated CSS:

.box {
    /* vendor prefixes excluded for brevity */
    transition: width 3s linear,
                height 3s linear;
}

.change-size {
    width: 300px;
    height: 200px;
}

Here we’re using jQuery to add the specified class on the element that is supposed to animate. Then the animation itself is defined in the CSS, where it’s easier to deal with.

This might not work for every possible situation, but it accomplishes exactly what we want – it separates the logic from the effect, avoiding scripts that are littered with CSS value declarations.

Now that we understand that concept, let’s look at how we can use JavaScript to trigger actions when these CSS3 effects have completed.

Executing Code When Transitions End

One of the useful parts of changing CSS values using jQuery’s .animate method is the callback function that fires when the animation is complete. Unfortunately, jQuery’s addClass, removeClass, and .toggleClass methods (one of which is used in the code above) don’t include an option for a callback. Other jQuery methods might also have this limitation.

As an alternative, however, you can use JavaScript to detect when a transition on an element has completed. This way we can still have an optional callback-like effect.

Here’s how such code might look:

var myButton = $('#button'),
       myBox = $('#box');

myButton.click(function () { 

    myBox.toggleClass('change-size');

    myBox.one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend',   
    function(e) {

    // code to execute after transition ends

  });

});

You can view this code in action at this JS Bin. In that example, I’ve added an extra line that writes a message to the page each time the transition completes.

So what’s happening in the code? After caching our DOM elements, first we toggle the class name when the button is clicked. After that, we bind the transitionend event using jQuery’s .one method (vendor prefixes added for full compatibility, including two for Opera).

Next we run the part of the code that we want to execute after the end of the transition. The .one method (as opposed to .on()) is necessary to ensure that the code executes only once.

Executing Code When an Animation Ends

Now let’s try the same thing with a keyframe animation. Our CSS will have a chunk that looks like this:

.box {
    width: 100px;
    height: 100px;
    background: hotpink;
}

@keyframes growBox {

    to {
        width: 300px;
        height: 200px;
    }

}

.change-size {
    animation: growBox 3s linear 0s 1 normal;
}

Then, our JavaScript is as follows:

var myButton = $('#button'),
       myBox = $('#box');

myButton.click(function () { 

    myBox.addClass('change-size');
  
    myBox.one('webkitAnimationEnd oanimationend msAnimationEnd animationend',   
    function(e) {
    
    // code to execute after animation ends

    myBox.removeClass('change-size');
    });

});

You can view a working version of this code in this JSBin.

This code is very similar to the one we used for transitions. The differences are as follows: We’re using the animationend event in place of transitionend, and we’re adding and removing the “change-size” class, rather than toggling it.

Summary

In conclusion, here’s a summary of what I’ve covered here, and then some resources for further reading:

  • Separate logic from effect by using JavaScript/jQuery to trigger events while reserving CSS3 for the effects they trigger
  • Use transitionend to detect when transitions have ended, allowing for callback-like behaviour on jQuery methods that don’t allow callbacks
  • Use animationend in the same way in relation to CSS3 keyframe animations

Further Reading

4 Responses to “Using jQuery to Detect When CSS3 Animations and Transitions End”

  1. salzz4u on April 26, 2013 at 1:13 pm said:

    awesome post! thanks for sharing

  2. RESPECT! Thank you so much for this function.

  3. Alex Bell on July 18, 2013 at 3:15 pm said:

    Great writeup. But FYI there is no such thing as msTransitionEnd IE9 didn’t support transitions, and IE10 supports it unprefixed: http://caniuse.com/css-transitions You might update the post.

  4. Great post. I’m using this technique on my current project where I need to trigger a callback action after a css3 animation has ended.
    Thanks for the post.

Leave a Reply

Learn to code with Treehouse

Start your 14 day free trial today and get access to hundreds of video courses in web development, design and business!

Learn more