Paul Irish

Making the www great

Why Moving Elements With Translate() Is Better Than Pos:abs Top/left

Update (2016): The more canonical writeup of this technique is at High Performance Animations - HTML5 Rocks. TL;DR: Only transform & opacity; never top/left!

In modern days we have two primary options for moving an element across the screen:

  1. using CSS 2D transforms and translate()
  2. using position:absolute and top/left

Chris Coyier was asked why you should use translate. Go read his response which covers well why it’s more logical to move elements for design purposes (with transform) independent of your element layout (with position).

I wanted to answer this with Chrome and get some good evidence on what’s going on. I ended up recording a video on the experience:

It’s a good watch and dives into Chrome DevTools’ Timeline, compositing, paint cost, accelerated layers, and more… but if you want the abbreviated text version, read on:

First thing, Chris made some simple demos to try things out:

This sorta works, but there is such low complexity in this situation that it’s all going to look pretty great. We need something closer to a complex website to properly evaluate the two (thx joshua for the macbook!):

Now we’re starting to get closer, but immediately I get distracted by something.

Distraction: Pixel snapping

If you run the demo above you might notice the top edge of the MacBook looks a little bit better in the top/left one. (And here I am writing a post about why translate is better! Preposterous!) So this is due to the absolute positioned macbook sticks to pixel positions, whereas the translate()‘d one can interpolate at sub-pixel positions.

One of the Chrome GPU engineers, James Robinson, called this the “dubstep effect”, as these pixels appear to be getting pounded by bass. Here’s a closeup of the effect… watch the top white edge of the macbook in each:

On the left, you see stair-stepping down three pixels and back up again. This pixel snapping may result in a less distracting transition in this case, though this wouldn’t be so noticeable if you were moving objects with less of a high-contrast situation.

Back to performance

If you run DevTool’s Timeline Frames mode on these two examples here, they start to tell a very different story:

The top/left has very large time to paint each frame, which results in a choppier transition. All the CSS including some big box shadows, are computed on the CPU and composited against that gradient backdrop every frame. The translate version, on the other hand, gets the laptop element elevated onto it’s own layer on the GPU (called a RenderLayer). Now that it sits on its own layer, any 2D transform, 3D transform, or opacity changes can happen purely on the GPU which will stay extremely fast and still get us quick frame rates.

Watch the video above towards the end to see more on how to diagnose paint costs, see what areas are being repainted, and evaluate what elements are on the GPU.


Click through below, try adding more and see how the the framerate reacts. Feel free to open up DevTools, too and explore Timeline:

Guidelines for animation

  1. Use CSS keyframe animation or CSS transitions, if at all possible. The browser can optimize painting and compositing bigtime here.
  2. If needs to be it’s JS-based animation, use requestAnimationFrame. Avoid setTimeout, setInterval.
  3. Avoid changing inline styles on every frame (jQuery animate()-style) if you can, declarative animations in CSS can be optimized by the browser way more.
  4. Using 2D transforms instead of absolute positioning will typically provide better FPS by way of smaller paint times and smoother animation.
  5. Use Timeline Frame’s mode to investigate what is slowing down your behavior
  6. “Show Paint Rects” and “Render Composited Layer Borders” are good pro-moves to verify where your element is being rendered.

Chrome Canary for Developers

If you do front-end web development and already use Chrome as your development browser, I encourage you to use Chrome Canary.

A new Chrome Canary build is available daily (we cut at 2am PST and take the best of last 40 revisions, to be specific). Running fresh builds gives you great goodies to look forward:

  • Chrome DevTools features
  • Features for the web platform
  • Large, experimental features (go visit about:flags)
    • Right now, there’s exciting stuff like Web Component’s Shadow DOM, WebRTC’s Peer Connection, and more.

Canary runs side by side

The other reason why Canary is great is because it can run side-by-side with your other Chrome install. In fact this is why the URL for Canary’s download page is “sxs”.

I recommend running Chrome Stable and Canary. That’s how most of the Chrome Developer Relations team does it. You never need to update your browser, you can watch the new stuff coming at you (and file bugs if it breaks) and still see what your users see.

11 Weeks From Canary to 310M Users

Fun fact: when a feature lands in Canary, it’s only a short 11 week trip down to shipping to all 300+ million Chrome users on stable. That is, as long as everything is on schedule and the feature doesn’t need to bake a little longer on dev channel before making its way down. Given that, it’s a smart move as a dev team to watch as features (and sometimes bugs) trickle down to have time to adapt. When a new stable Chrome is ready, all users will have it within just a few days.

Canary is available for Mac and Windows, but sadly not Linux. :( But luckily there are packages that track the dev channel Chromium that’ll keep you up to date on a weekly basis, so you can have a pseudo-canary. If you need a one-off build of the freshest Chromium available, just go to; it’ll detect your OS and serve up a build that’s less than a few hours old. Hotchachacha!

Protip: you can set Canary as your default browser : Canary itself doesn’t have a setting to let you do this, as its an edge release. (Read about how Chrome ensures the stability of the Canary build). However… if you open Safari’s preferences, Canary will be listed in the Default web browser choices, so you can choose it if you want all new links to open there.

Another small tip: sometimes your Chrome extensions affect your page inspection behavior is weird ways. Jump into incognito where extensions don’t run to get a clean look.

Live on the edge

Running Canary regularly rocks, but so do edge versions of other browsers:

Oh right, call to action:

2012.11.02: Added CTA thanks to philip_roberts’ suggestion.
2013-03-15: Accurate data on when/how we cut Canary builds.

Interview on Treehouse

The great folks at Treehouse sat down with me for 30 minutes to talk about frontend development, my background, HTML5 Boilerplate and tooling.

A few highlights:

  • 3:40 Where’d I grow up? What was I into? (Also, the supercool IE4 DHTML event I went to!)
  • 14:45 What’s my favorite feature inside the HTML5 Boilerplate?
  • 18:34 Will web development even out where we don’t need to fuss over so many fallback scenarios?
  • 22:52 Are abstractions okay? Should you always learn what’s going on under the covers first?

I’ve also updated the interview listing on my About page. <3z