Famo.us behind the scenes
WTF is Famo.us?
From Famo.us website:
Interacting with the DOM is riddled with performance issues. Famo.us abstracts away DOM management […] If you inspect a website running Famo.us, you’ll notice the DOM is very flat: most elements are siblings of one another. […] Developers are used to nesting HTML elements because that’s the way to get relative positioning, event bubbling, and semantic structure. However, there is a cost to each of these: relative positioning causes slow page reflows on animating content; event bubbling is expensive when event propagation is not carefully managed; and semantic structure is not well separated from visual rendering in HTML.
Famo.us promises a rich 60 FPS experience, and to do so, we needed to circumvent these inefficiencies.
But how exactly Famo.us works behind the scenes for some simple transitions?
One simple transition
Let’s take one transition as an example to see how Famo.us works. For this I chose the simple transition Facebook does when you hover your avatar. Take a look at the transition below:
So how does Facebook built the icon transition? First of all we have some nested elements, the cat is an img tag inside a div, and next to this div we have another div for the dark background which contains a link with the icon represented by an img. It uses a css transition that changes 3 properties: opacity, scale and bottom. All animations occur on .3 seconds and they use a cubic bezier as the transition curve.
As we are told, opacity and scale are cheap properties to animate, but bottom, just like all positioning properties is not. This probably explains why we can’t really see any bump in the opacity and scaling transitions, they look pretty smooth, but the same can’t be said about the vertical positioning of the icon, that at some point looks strange.
In order to see how Famo.us would handle this I’ve created a simple replica of this transition. The result can be seen here.
This is the case on both transitions using regular curves, line easeInOut and transitions that rely on physics like snap.
This is said to be the foundational chat of their startup:
“We use the CSS3 primitive -webkit-transform: matrix3d, which lets us compute the composite matrix and skip the browser’s renderer. No plug-in, no download, no hack. By appending this to each DIV, we can render the composite matrix and go straight to the GPU.”
“Um, that sounds like really hard stuff.”
“Not really. I’ll have it done by tomorrow.”
The result, compared to the – pretty decent, let’s say – Facebook implementation, is that, using devtools in my Chrome, I can see an almost constant 60 FPS frame rate, while on Facebook it can degrade to 30-something on the transition. Also, on Facebook I see some bigger parts of the screen being repainted whilst transitioning. In the image above, the green rectangle shows what is being repainted by the browser.
I’ve also tried to inspect how other libraries that are meant to improve transitions works. VelocityJS, one of the main contenders, basically replaces and improves jQuery’s animate method. On their page you can see how an animation behaves on 500 elements using jQuery and using Velocity. But again, it is just a replacement. If you’re animating positioning attributes, like left or top, it will still animate these elements, instead of coming up with a different transition that brings about the same result, with better performance.
Famo.us approach seems both simple and effective. It is meant for mobile, and it excels at it. But I don’t see why not to prototype desktop transitions on it and then implement something by yourself based on its approach.