Nuances of CSS Transitionend Events

Rob will have you saying “Hello” to the right solution and “Bye" to `transitionend` headaches.

I was recently working on some code that would handle a toggling menu’s open-close state after the animation had finished. In order to do this, we used the transitionend event to determine when we should modify the state of the DOM nodes to show the new state correctly. However, when the animation was ending it appeared that nothing was happening. After dropping in a debugger statement, it became clear that what was really happening was that it was firing twice—in quick succession—toggling the element open and closed so quickly that there was no visual effect at all.

Here’s a similar example. Clicking on Hello should show Bye once the animation is complete, but it doesn’t because of behavior of multiple transitions.

See the Pen grvgKB by Rob Tarr (@robtarr) on CodePen.

TL;DR;

The transitionend event is firing once for each property that is being animated, causing our toggle to fire multiple times. This results in an open-and-close action instead of just the open.

Specifying the propertyName in your transitionend event handler can prevent those handlers from doing more than they should. If you want to get right to the solution, jump down to Which Event do I Use? If you want to see some examples and get a feel for why this is happening, read on.

How to Solve This

Let’s look at a simple example to start.

See the Pen KrXLYK by Rob Tarr (@robtarr) on CodePen.

This will fire one event with a property-name of background-color.

If we change the transition to include a transform, we still have one transition property, but it has multiple values.

See the Pen dXdNpW by Rob Tarr (@robtarr) on CodePen.

You’ll also probably notice that each event fires at the end of its specified time, which is most likely what you would expect and want.

If we change the property we’re animating to, for example, border-color, we get an interesting result.

This will give us 4 events, one for each side of the box:

border-right-color
border-bottom-color
border-left-color
border-top-color

Other shorthand CSS properties (such as padding, border-width, etc.) will also respond with multiple events.

See the Pen EywzqW by Rob Tarr (@robtarr) on CodePen.

Which Event Do I Use?

Now that you understand how each of these events is firing and when, you need to be able to know which propertyName you want to trigger your code. You can do this by using the propertyName key on the event object (it’s what I logged to the console in the samples). It will contain the name of the property that just finished, so you can isolate your JavaScript to execute based on specific transitions.

So, looking back at the original example, we can fix the problem by making sure that we only fire the toggle code based on one specific transition ending:

See the Pen QEQdJL by Rob Tarr (@robtarr) on CodePen.

Go Forth And Animate

The transitionend event is a great tool to use when you need to sync up some JavaScript actions with your CSS animations. Just remember that if you’re animating more than one property, you’re going to get more than one event fired.