Web Animation using JavaScript: Develop & Design (Develop and Design)

(やまだぃちぅ) #1

Technique: Remove layout thrashing


Layout thrashing—the lack of synchronization in DOM manipulation—is the 800-pound
gorilla in animation performance. There’s no painless solution, but there are best practices.
Let’s explore.


Problem


Consider how webpage manipulation consists of setting and getting: you can set (update)
or get (query) an element’s CSS properties. Likewise, you can insert new elements onto a
page (a set) or you can query for a set of existing elements (a get). Gets and sets are
the core browser processes that incur performance overhead (another is graphical
rendering). Think of it this way: after setting new properties on an element, the browser
has to calculate the resulting impacts of your changes. For example, changing the width of
one element can trigger a chain reaction in which the width of the element’s parent,
siblings, and children elements must also change depending on their respective CSS
properties.


The UI performance reduction that occurs from alternating sets with gets is called
layout thrashing. While browsers are highly optimized for page-layout recalculations, the
extent of their optimizations is greatly diminished by layout thrashing. Performing a series
of gets at once, for example, can easily be optimized by the browser into a single,
streamlined operation because the browser can cache the page’s state after the first get,
then reference that state for each subsequent get. However, repeatedly performing one
get followed by one set forces the browser to do a lot of heavy lifting since its cache is
continuously invalidated by the changes made by set.


This performance impact is exacerbated when layout thrashing occurs within an
animation loop. Consider how an animation loop aims to achieve 60 frames per second,
the threshold at which the human eye perceives buttery-smooth motion. What this means
is that every tick in an animation loop must complete within 16.7ms (1 second/60 ticks ~=
16.67ms). Layout thrashing is a very easy way to cause each tick to exceed this limit. The
end result, of course, is that your animation will stutter (or jank, in web animation
parlance).


While some animation engines, such as Velocity.js, contain optimizations to reduce the
occurrence of layout thrashing inside their own animation loops, be careful to avoid layout
thrashing in your own loops, such as the code inside a setInterval() or a self-
invoking setTimeout().


Solution


Avoiding layout thrashing consists of simply batching together DOM sets and DOM
gets. The following code causes layout thrashing:


Click here to view code image
// Bad practice
var currentTop = $(“element”).css(“top”); // Get
$(“element”).style.top = currentTop + 1; // Set
var currentLeft = $(“element”).css(“left”); // Get

Free download pdf