Performance and Web Animation

The last few years the mobile web is growing really fast, but there are still lots of problems that must be solved in order to achieve a better user experience. One of these is web animations and performance. Usually well-performed animations run at 60 frames per second (fps), and believe me or not that is possible, but not always easy.

CSS Animations

Please stop trying to animate unanimatable CSS properties: I have seen a lot of times people trying to animate width/height/top/left properties, etc. Currently there are only two things that can be animated with good performance: transform and opacity. As you can see in the video below, the difference is drastic between animating top/left and transform, because transform is GPU optimized and will cost you only composition work which is cheap compared to layout and painting. Open your timeline in Chrome DevTools and test.

There is also a website called CSS Triggers where you can find what it costs you to animate a certain property. Use it please! Use it and always measure, test on real devices, but don’t do it on the latest Samsung flagship model! Try using a 3–4 year old device, your users probably don’t have super-duper smartphone.

I know for some animations you will need more than transform, but you always can use JavaScript to calculate positions, offsets etc. There are plenty of functions like getBoundingClientRect (be careful, some of them also could trigger painting or layout). Use FLIP.js, a really good idea by Google engineer Paul Luis.

Extract and compose elements

Maybe you want to animate border or box-shadow, but before you start doing, think for a moment. Can you actually extract those properties as separate elements? In most of the situations you can do it. Check the examples below, they are simple but will give you some ideas how to extract elements which, most importantly, could be huge performance improvement.

animating border
animating box-shadow

Will-change

The will-change property could optimize your animations. It tells the browser “I am planning to animate this and that later, so take care of that”. The browser creates a new layer (the same layer created by z-index) and it is usually easier to “move” those layers around. Something very important: don’t abuse it. Too many layers mean too much memory consumption, and not all smartphones have 6GB of RAM.

requestAnimationFrame

requestAnimationFrame is a JavaScript API that replaces the horrible setInterval animations. Even jQuery 3 finally migrated to it. As the function name says, it just requests a frame in which theoretically an animation runs at 60 fps.
requestIdleCallback is another hero (unfortunately it currently only works in Blink-based browsers): it allows kind of rescheduling any non-essential JavaScript work to a moment when the browser has free (idle) time. That doesn’t mean after 5 or 10 minutes, usually some milliseconds later, which could be very useful for any background sync etc.

WebWorkers

WebWorkers are a pretty old thing (for the web standards), they run in a separate tread (multi-treading in a browser). I have seen a lot of experiments the last few months. The idea is to put all heavy browser work into a WebWorker and to do only UI stuff in the main thread (by the way, WebWorkers don’t have access to the DOM). Some people go even further with that using virtual DOM and only apply DOM changes in the main thread. Angular 2 is going to have this feature out of the box and it seems like other popular JavaScript frameworks are working in that direction as well.

Please do it

I know is not so easy, but at least WE MUST TRY. Our users deserve better user experience.