Animation for the web has been around for a long time. In the early days, motion was handled through the gif format. Introduced in 1987, gifs allowed limited looped animations on an otherwise mostly static web.
In the late 1990s Adobe Flash entered the picture, which allowed high quality audio and video to be transferred over the very limited networks of the time. Motion in logos or text became somewhat common, and cartoons done in Flash started to become popular.
These worked for a while, but the early tools were fairly limited. Slow connection speeds of the time meant long load times, and limited browser power often resulted in jerky animations. As cable speeds increased so too did the amount of content, offsetting old gains. High levels of media, animation, and interactions were are a trend that isn’t going to stop anytime soon, so more efficient methods and tools needed to be developed.
With any animation smooth, fluid motions are a high priority. Unlike a recorded video however, animations in a browser will depend greatly on how well that browser handles them, as well as the efficiency of the animation implementation itself.
Hardware acceleration is the first thing to be aware of. In certain conditions the browser will offset some processing to the GPU. This allows for faster processing than might be done with the general cpu handling other browser tasks. There are five properties that trigger hardware acceleration: The transform functions rotate, scale, skew, and translate, as well as the opacity property.
These five properties allow for most common web animations to be more efficient than other methods of accomplishing the same goal. For example, animating an element from left:0px to left:1000px accomplishes the same outcome as using transform: translateX(‘1000px’), but only the latter is accelerated. Additionally, changing the left property (as well as many others) will require the DOM to update the tree, recalculate the layers, and re-composite the page. The hardware accelerated properties avoid this inefficiency by only altering the composite, which is much easier for the browser.
This means that alternating between reading and writing elements is significantly more taxing than doing all the reads first followed by all the writes. This can be an extremely easy trap to fall into. Grouping the getter and setter is common in coding, and unless you’re watching the Timeline closely there’s no warnings. Further, thrashing can be triggered indirectly through nested functions, making them difficult to spot.
Since repainting is very taxing on the browser, we should try to limit the number of times its triggered. While fixing the thrashing example above greatly helped our repaint rate, its still causing paints to happen individually. But what if we could collect the cases where a repaint is needed, and do them all at once? That’s what #requestAnimationFrame is for. By passing in a callback function, the browser can queue changes to be completed together during the next scheduled paint. This reduces a lot of redundancy and helps optimize the animation against stutters and chop. Plus, requestAnimationFrame has an added benefit of halting our animations when in background tabs, since no frames are being drawn. This can greatly improve performance as it frees up processing power.
requestAnimationFrame can even be called recursively, achieving the effect of setInterval. This method has an opposite in cancelAnimationFrame, which allows a request to be removed from the queue similar to unbinding a listener.
Libraries and Frameworks
Libraries and frameworks allow developers to use advanced features by using prewritten code. When it comes to animations there are many of these, but some of the big ones are jQuery, three.js, and D3.js. Though they all have different features, these libraries can be very powerful to quickly build cross browser animations or create complicated motions without reinventing the wheel.
Seems faster is faster
While optimizations and efficiencies are important, sometimes being faster on paper isn’t the best decision. As a rule of thumb, whichever action is perceived as faster will be the better option even if its technically slower. Things like lazy loading of images and loading scripts at the end of the body tag can help speed this perception up. When working in animations, there may be methods of dividing processing to increase user perception.
Have a comment or question? Send us a note. It won't be shown here and email isn't required, unless you'd like a