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.
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.
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.
This will fire one event with a
If we change the
transition to include a transform, we still have one transition property, but it has multiple values.
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.
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
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:
Go Forth And Animate