A Tale of Animation Performance

Hey @chriscoyier, do you have any source confirming translate() is better than top/right/bottom/left for moving objects please? :)— Hugo Giraudel (@HugoGiraudel) December 10, 2012

Context

So we're all on the same page, what Hugo means is, there are two different ways you can "move" elements.

Give the element relative, absolute, or fixed positioning. Then you can use the top, right, left, bottom (or any combination therein) to move the objects around.

Ensure the element had a display value of block or inline-block and then use the transform value translate(), translateX(), or translateY() to move the element.

"Better", v1

My first thought on what "better" meant in this context is which one is more appropriate to use under different circumstances. Which leads me to say: "don't confuse positioning with design-y motion."

Case in point. You have a button. You want to apply an effect to that button so that in it's :active state it nudges down 2 pixels to mimic a "pushed" effect. That is a design-y motion that should be done with translate(). You could do it with top or bottom and relative positioning, but then you are confusing the concepts of positioning and design-y motion.

Let's say somewhere else in the app you absolutely position a button (perfectly legit). Now when that top: 2px; gets applied to the button in it's :active state, that button will likely go zooming off someplace you didn't expect, possibly making the button unclickable.

Using translate() will always "nudge" the element from it's current position which is perfect for an effect like this, or really any design-specific motion.

"Better", v2

What Hugo was more likely getting at is performance. It has become common generic advice that using translate() to move elements has better performance than using top/right/bottom/left. But does the data hold up? Let's take a look.

To start, I made a very simple animation of a red ball animating back and forth.

To my naked eye, in the latest stable Chrome (23) and a Retina MacBook Pro loaded with RAM, the translate() version does perform slightly better. I can see very slightly choppiness on the top/left version. Perception is important, but let's look at real data.

In the Chrome dev tools, you can click over to the "Timeline" tab, then onto "Frames", and then press the circle "Record" button along the bottom. With the animation running, start the recording for a little bit then stop it. The data is best if no other web sites are visible particularly if they are doing any animation.

In the top/left version, you can see occasional spikes above the line marked "60 FPS", or sixty frames per second. That's the line we try and stay under as that equates to perfectly smooth perceived motion.

Spikes above line == choppiness.Smooth

But wait

This gets more complicated. I started talking with Paul Irish who works on the Google Chrome team. Paul thought that because these "paints" are so simple, it's probably not the best true performance indicator. Paul took my demos and upped the complexity. Instead of a red ball, Josh Hibberts MacBook Pro. Instead of a white background, Nate Eagle's upholstery.

Things got weird when Paul's examples showed the reverse of what we expected. The top/left version looks smoother than the translate() version. And surprisingly, the Frames timeline didn't show any big differences.

This is where Paul started to dig a lot deeper into this weird world. He came up with lots of interesting stuff! Paul talked to another Paul on the Chrome Team, Paul Lewis, who agreed that it is "smarter to use translate() for design-y motion." But went on to say that there is more to this than frame rate. With translate(), you get sub-pixel animation which is a kind of blurring between pixels that usually leads to smoother animation.

With subpixel [animations] you lose clarity, which is correct. The key is to hold for longer on rounded values at the extremes so your eyes get the satisfaction of clarity but the smoothness of motion.

Changing top/left/right/left moves the DOM element inside window. So it means everything is recalculate and redraw (since those modifications could change how other elements behave).
using translate(), you’re not touching anything in the DOM & how it behaves. Only how it renders. That’s a HUGE difference that explains the performance difference first, then also make things working differently. The element itself move, with all its CSS, rather than changing its CSS parameters.

You can see this difference using a background-attachment: fixed and then change top/left values, or change translateX() value.

Right you are. I swore I saw a demo somewhere where the thing moved on :hover and the hot area stayed put . . . Must have been something else.
And a brave soul to use JSFiddle instead of CodePen around these parts! :)

This feels like a dumb question, but, is there any difference in browser compatibility of the two methods? and/or any difference in ease of writing browser-compatible CSS? (is either more or less compatible, does either lend itself to simpler coding with fewer CSS work-arounds, etc.?)

Things got weird when Paul’s examples showed the reverse of what we expected. The top/left version looks smoother than the translate() version. — In Firefox 17.0.1 in Win7 x64 translate() looks WAY smoother than top/left, but only after the object has moved the first time. The first time the object moves, it does look choppy.

This is great! I’ve always remained a top/left/bottom/right guy for doing stuff like sliding in menus simply because translate isn’t supported in IE8, and I didn’t feel like writing extra CSS. However, this definitively proves that using translate is worth the extra effort. Duly noted.

I noticed the SwipeJS library was using translate for 1:1 swiping and animations on smart phones. I was curious why the author was using translate, so I replaced it with a negative margin and then with position:relative to compare. The difference was huge, so I quickly switched back to translate. On mobile clients, where computing power is limited, it’s the difference between very choppy, and smooth animations.

I read that in order to activate iPhones hardware acceleration you needed to use translate…

I found this to be true when I made a simple dropdown using jQuery slideDown/slideUp…it was choppy on the iPhone…but when I switched to just switching out classes and using transitions and translate the performance was much better…

Here on FF17, translate() is MUCH better, especially when I hit “Add 10 more Macbooks”.
Using top/left, the animation is very choppy and the sub-elements (like the opening) lid do not all move together with the rest of the macbook.

This just proves why multiple weekly visits to css-tricks/Coyierland is imperative. They address every little web nuance with scientific discipline, drilling down to accurate info time after time. One of the www’s consistently best info resources. Minor but interesting question, brilliant links and responses for advanced knowledge. Kudos again.

I know I’m a little late to the party, but I thought you guys might find this interesting…

I’m seeing that top/left is MUCH faster in most browsers when more elements are animated. See the comparison at http://www.greensock.com/js/speed.html. The translate() technique is literally 400% slower (or more) under heavy stress. the only exception is iOS Safari. Weird.

So I think the performance gains you’re seeing with translate() are only applicable in certain scenarios like when a few elements are animating concurrently and/or they use effects like opacity, box-shadow, etc. But there’s a threshold where the “hardware acceleration” juice actually becomes a significant bottleneck (thanks to Paul Lewis for pointing that out). Then again, the sub-pixel rendering can be nice if you’re not animating many elements.

Just to add my findings: Chrome latest (23.0.1271.97) looks much smoother in the complex example using translate() with 1 Macbook, but most weirdly the performance doesn’t degrade when adding tonnes more Macbook images, whereas the top/left grinds to a halt exponentially! Must be some kind of super-awesome optimization going on that I could never hope to understand.

Nice post, I have found that the latest builds of FF and Chrome are much smoother, but the fact remains that we want to move towards using lots of nice CSS3 effects, but the user’s are holding this back on projects… At the end of the day as a developer you must build a site that is as usable as possible for the user base.

Careful if you use this method to animate a panel containing form elements (Firefox bug): when those elements are focus (or text inputs are typed in) the panel will move independently of any values you use to detect or reposition the panel (and the values will be out-of-sync). It’s annoying. There’s a bug report somewhere at mozilla.

in the mac book examples the translate is very smooth and top/left is laggy for me in both firefox and chrome. how do you say top/left is smoother??

This comment thread is closed. If you have important information to share, you can always contact me.

Treehouse is where you go to learn HTML, CSS, and how to build iOS apps. It's a complete education in modern web and app technology, designed to get you ready for a hot new job or to kickstart your own business.

The Lodge is a member login only area with access to video training on how to build websites from scratch using the best modern tools.

What now? I have some ideas for you.

Go explore CodePen!

As a front end designer and developer, you should have an account on CodePen so you can save your snippets, present your ideas, and engage with other front end folk. I'd encourage you to go PRO as well, to unlock the full power of CodePen.

Get the newsletter!

You should sign up for the CSS-Tricks newsletter. It's a clean copy of all the blog posts each week, combined together, right to your inbox. If email isn't your thing, there is an RSS feed, iTunes, and lots of other ways to subscribe.

Listen to ShopTalk!

Subscribe to The Lodge!

The Lodge is a members-only, ad-free video learning area here on CSS-Tricks. Just like the free screencasts, but organized into four large complete series. Membership is also the #1 best way to support CSS-Tricks.

We can do the real footer now.

Site Links

Colophon

CSS-Tricks* is created, written by, and maintained by Chris Coyier. It is built on WordPress, hosted by Media Temple, and the assets are served by MaxCDN. The fonts are Source Sans and Source Code Pro. It is made possible by viewers like you who subscribe to The Lodge and through advertising for products and services I like.