Animations on Fire

Brian Birtles, Mozilla Japan
Graphical Web 2014, Winchester

Animation is awesome…

Source: Christopher Price 2013,
UVNdotTV 2011,
Twitter 2011,

Animation is awesome…

Scripted animation as displayed on Firefox and Chrome on Android HTC J

setAttribute vs SVG DOM

* Times are ms taken for 100,000 iterations averaged over 5 runs (lower numbers are faster)
Browser cx
setAttribute('cx', 'X') cx.baseVal.value = X % improvement
Firefox 34 246.6 131.4 47%
Chrome 36 155.8 20.4 87%
IE 11 2347.6 1897.4 19%
'translate(X, Y)')
matrix.{e,f} = {X,Y}
% improvement
Firefox 34 258.4 224.8 13%
Chrome 36 199.6 30.6 85%
IE 11 1922.8 2592 -35%

More realistic test
Try using a specialized API to avoid parsing
Using display:none

Using display:none

* Average result after 3~5 runs. Higher numbers are better.
Browser Unoptimized With display:none Avg. improvement
Firefox 34 25.6fps 29fps 3.4fps / 13%
Chrome 36 5.1fps 12.5fps 7.4fps / 145%
IE 11 4.8fps 7.8fps 3.0fps / 63%
Remove elements from the render tree with display:none
Profiler in Firefox
Profiler in Chrome

Reflow logging in Firefox

Triggering layout

* Based on my inspection of profiles from this test case.
property Triggers layout?*
Firefox 34 Chrome 36 IE 11
left (position: relative)
left (position: absolute)

Avoiding reflow

Try transform instead of top/left/marginTopetc.
Try animating elements that are position:absolute.
Try non-geometric properties like color, opacity etc.
Try transform: scale instead of font-size.

Let sleeping dogs lie

What triggers recalc / reflow?

  • window.getComputedStyle(elem).color → style recalc (typically)
  • window.getComputedStyle(elem).width, elem.offsetTop, elem.getClientRects() etc. → reflow

Don't do this

for (var i = 1; i < containerElem.children.length; i++) {
  containerElem.children[i] =
    containerElem.children[i-1].offsetTop + 10 + "px";

Avoiding forcing reflow

* Average result after 3~5 runs of test A and test B. Results for Firefox were particularly variable but were generally only slightly faster since the test animates the top property which does not trigger reflow in Firefox.
Browser Triggering reflow Not doing that Avg. improvement
Firefox 34 42.1fps* 45.8fps* 3.7fps / 9%
Chrome 36 10.5fps 23.2fps 12.7fps / 120%
IE 11 8.2fps 19.1fps 10.9fps / 132%
Try reading computed style (especially geometry) less often or not at all.

Paint cost

Paint area
Paint complexity

Paint flashing (Firefox)

Paint rectangles (Chrome)

Paint flashing #1

Paint flashing #2

Paint flashing #3

Paint complexity

  • box-shadow
  • border-radius
  • SVG filters…
Animating stdDeviation on <feGaussianBlur>33fps
Animating transform (scale) of blurred copy → 49fps
Try replacing expensive effects with simpler ones


Browser <iframe src="svg"> <img src="png">
Firefox 34 1.9 fps 49.5 fps
Chrome 36 11.18 fps 49.7 fps
IE 11 5.8 fps 50.9 fps
Pre-render expensive assets


* Some rendering defects
Browser <iframe src="svg"> <img src="svg"> <img src="png">
Firefox 34 1.9 fps 49.1 fps 49.5 fps
Chrome 36 11.18 fps 13.0 fps* 49.7 fps
IE 11 5.8 fps 15.5 fps 50.9 fps
Try using <img> to embed SVG images instead of <iframe> (or <object>, <embed>).

Hardware acceleration

  • Paths, text Not much
  • Filters Coming
  • Compositing OK

What gets a layer?

Animated transform
Animated opacity
3D transform

Inspecting layers

  • Firefox: about:config
    layers.draw-borders to true
    (requires layers.offmainthreadcomposition.enabled to be true)
  • Chrome: DevConsole → Rendering → Show composited layer borders

Inspecting layers

Inspecting layers

Animated transform
Animated opacity
3D transform

Layers and transitions

Layers and SVG Animation

Layers and scripted animation

Starting an animation

Enter will-change

  • will-change:<property>
    • will-change:transform
    • will-change:opacity
  • will-change:scroll-position
  • will-change:contents
  • transform:translateZ(0)
  • Firefox: need layout.css.will-change.enabled in about:config.

Applying will-change

Your browser is a jank

Compositor animation

Animation on the compositor

Not so fast…

  • Representable by compositor? (e.g. transform, opacity)
  • Supported platform? (e.g. Firefox OS)
    (layers.offmainthreadcomposition.async-animations → true)
  • Other limitations: top/left also animated?
  • Controlled by the browser? (e.g. CSS Animations)

What about script?

elem.animate({ transform: 'rotate(360deg)' },
             { duration: 1200,
               iterations: Infinity });