Presented at Web Unleashed 2017. More info at www.fitc.ca/webu
Presented by Alexander Blom, Isle of Code
Overview
Adding animations to web and hybrid apps can be challenging. Aside from choosing technique, you are often left with jank and less than desirable performance.
Objective
Audience members will leave with a better understanding of animation performance & pitfalls desktop and mobile context.
Target Audience
Web/Hybrid developers looking to improve animation performance.
Assumed Audience Knowledge
Basic JS/CSS assumed
Six Things Audience Members Will Learn
What are my choices when needing to animate?
What changes in a mobile context?
What are the tradeoffs and how do I decide?
What are the common pitfalls?
How do I debug performance problems?
Getting a smooth animation.
8. FPS Target
• 60fps is considered best;
• 1000ms / 60fps = ~16.6ms per frame;
• 60fps is not always achievable!;
• It is better to deliver a consistent frame rate
than a variable one. Consider targeting 30fps;
9. Animation Options
• Declarative: CSS;
• Generally speaking most performant;
• Browser knows what is happening up front -
can save you from yourself;
• Can become complex to write;
10. Animation Options
• Imperative: JS;
• Tell the browser how. Easier to spell out in
code (e.g. bounce);
• Run on the main thread (not great);
• requestAnimationFrame & webAnimationsAPI
can fix performance issues - to be discussed
later;
16. What causes Reflow?
• Resizing the browser window;
• using JavaScript methods involving computed
styles;
• adding or removing elements from the DOM; and
• changing an element's classes.
• https://developers.google.com/speed/articles/
reflow
17. How our content is rendered
• 1: DOM Tree constructed;
• 2: Layout (recursively from the top left);
• 3: Paint;
19. Paint Styles
• opacity is a special case;
• If the element has its own layer, this is handled
automagically by lowering the alpha-mask value;
20. How our content is rendered
• 1: DOM Tree constructed;
• 2: Layout (recursively from the top left);
• 3: Paint;
• 4: Composite/Layering (default is a single layer);
21. Layers
• Default is a single layer;
• Composed layer more efficient to animate - GPU;
• Pushing every node to it’s own layer is the worst case;
• The most performant is hardware accelerated
properties on composite layers (e.g. transform/
translateX);
• Layers are expensive (width * height * 3);
40. Some of our problems
• Big FPS dip;
• Each animation is triggering a reflow;
• We are not taking advantage of hardware-
accelerated properties;
• We are redrawing at a fixed (but not) rate;
• Will keep running in an unfocused tab;
41. We are redrawing at a fixed
rate
• Sort of:
• interval timing is not guaranteed - if our thread
is busy it will take longer;
• When a tab is inactive the interval will still fire
every ~1s;
56. Profile
• 6248ms to 5420ms on scripting;
• 10588ms to 4818ms rendering;
• 267ms to 1488ms painting;
57. Some of our problems
• Big FPS dip (sort of);
• Each animation is triggering a reflow;
• We are not taking advantage of hardware-
accelerated properties;
• Will keep running in an unfocused tab;
• We are redrawing at a fixed rate;
59. animationFrame
• Supported for major browsers;
• Only draws when:
• the animation will be visible;
• the browser is ready;
• there are no other frames waiting to be drawn;
• Eliminates unnecessary draws & overloaded
callbacks;
65. Profile
• 5420ms to 2605ms on scripting;
• 4818ms to 5295ms rendering;
• 1488 to1557ms painting;
66. Some of our problems
• Big FPS dip;
• Each animation is triggering a reflow;
• We are not taking advantage of hardware-
accelerated properties;
• This will keep running in an unfocused tab;
• We are redrawing at a fixed rate;
67. Still could be better
• Immediate reaction may be to tear down unused
elements;
• Don’t
73. Intersection Observer API
• “The Intersection Observer API provides a way
to asynchronously observe changes in the
intersection of a target element with an ancestor
element or with a top-level document’s.”
• https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
77. Passive Event Listener
• Allows you to indicate preventDefault will not be
used - e.g. eliminates block on scroll
78. My best practices
• Avoiding JS Animation API until better Safari support;
• Pages with smaller animations (e.g. button bounce):
• CSS/Hardware accelerated animations are fine;
• Will generally promote frequent/transitional
animations to their own layer;
• Pages with lots of animations:
• Just use animationFrame;