Guaranteeing a CSS transition will actually happen

Let’s say you have a <div> on your page, and you want to slide another <div> on top of it. And, because you’re a good developer, you want to use hardware accelerated CSS to do it. Pretty simple – make a <div> that’s hidden off to the right, then apply CSS that will slide it in. Like so:

Except, when you try the result tab, you’ll see that the new element appears instantly, rather than sliding in. Why? Well, because an appendChild call doesn’t actually add the element there and then – it adds the operation to a queue, to be executed the next time the browser has a DOM repaint event. Which doesn’t happen until after all your JS has run. By the time your <div> is actually added to the page it already has the transform CSS removed.

So, what to do? Wrapping it in a window.requestAnimationFrame seems to work. Most of the time! Unless there’s a lot of other stuff happening!

As the Mozilla documentation states, requestAnimationFrame actually “requests that the browser call a specified function to update an animation before the next repaint”. So it actually does the opposite of what we want – we’re just lucking out that a repaint event has occurred in between anyway. Using a 0ms setTimeout has the same effect. The best chance we have of guaranteeing our slide transition happens is to use a 10 or 20ms delay, and just hope the browser has repainted in the interim.

Gross. Mozilla has a MozAfterPaint event that sound do what we want – except it is only available to addons. So, how do we fix this?