
60 FPS Animations with CSS3 - ritadias
https://medium.com/outsystems-experts/how-to-achieve-60-fps-animations-with-css3-db7b98610108
======
russellbeattie
Animations via CSS have been a challenge in my experience. It's easy to create
a demo with a single layer of DOM elements and have it work well, but as soon
as there is overlap of any sort, lots of DOM elements to manipulate, or things
like images or media, it can get twitchy real fast. In addition, every browser
and every platform is different in rand ways.

I was doing testing on a scrolling carousel and couldn't figure out what was
causing a stutter that appeared in an Android WebView, but not in the
equivalent Chrome version on a Mac. It turned out that the desktop browser was
doing an additional recalc in the middle of a bunch of other animations. I
ended up slotting in a document.body.getBoundingClientRect() to force the
recalc and make them work equivalently. You might think this would cause
thrashing, but it actually smoothed things out. Crazy but true.

Also, CSS animations can "cancel" in odd ways... if I tell an element to
translateX from a to b, then during the animation, tell it to actually go to
c, some browsers will figure it out (most) and do the right thing, some will
"start over", some will do wonky things with the speed (does it calculate the
duration from the current position in between a and b, or from a?).

Don't get me wrong, CSS3 animations are great, but don't make the mistake that
they "just work", because they don't.

~~~
paulddraper
Similar experiences.

CSS3 animations are cool because they have the potential to be superior, but 3
out of 4 times it seems that the equivalent JS/$.animate is smoother and more
consistent.

It's the not the reality I want, but it's the one I've been shown.

~~~
SOLAR_FIELDS
It's very situational. I built a rich SPA with lots of animations a few years
ago and sometimes I would have no issues and other times animations would chug
on one or two browsers. I haven't done animation work in the past couple of
years but I used GSAP for that product and it was great. It's very tough to
navigate the animation world because fades work great in context A on FireFox
but work like crap in the same context on Safari. You might see the opposite
on context B with a different animation.

Hopefully in a few more years we will see better and more consistent
performance across all browsers, but we aren't quite there yet with CSS

------
jdauriemma
This article was useful and concise.

I urge web developers to consider the trade-offs when using CSS hardware
acceleration. Properties like `will-change` or `transform3d` substantially
increase the client device's energy usage. This has battery-life implications
for users on portable devices such as laptops, tablets, and mobile phones. As
with any other feature, ask "why" before "how" when prioritizing interactive
motion in your webapp.

More info: [https://dev.opera.com/articles/css-will-change-
property/](https://dev.opera.com/articles/css-will-change-property/)

~~~
michaelchisari
A nice feature would be to add an "energy saver" option to your web app, which
adds a class to your app and a stylesheet that disables all animations.

~~~
myfonj
In user styles capable browsers you can disable CSS3 animations pretty easily,
just using

    
    
        *, *::before, *::after
        {
          transition: none  !important;
          animation: none !important;
        }
    

(For not-so-capable browsers using author level pseudo-user-style sheets the
`star` must have raised specificity, like `:not(#\0)`.)

I used this in the past when I wanted to play 2048 as fast as possible,
resetting also border-radius, text-shadow, box-shadow, text-rendering, image-
rendering and background-image [1]. It really made quite a difference :]

[1]
[https://userstyles.org/styles/103878/nofx](https://userstyles.org/styles/103878/nofx)

~~~
uwu
`transition: none` breaks pages relying on the "transitionend" js event (edit:
and i guess the other transition-related events i forgot about), i noticed
logging into google wouldn't work with it (it wouldn't hide some gray overlay)

here's what i use instead:

    
    
      /* forgot if this was needed but i think using !important here broke something */
      transition-property: none;
      
      /* maybe not needed */
      transition-delay: 0!important;
      
      /* non-zero to support "transitionend" event */
      transition-duration: 0.0000001s!important;
      
      /* possible tiny optimization */
      transition-timing-function: linear!important;
    

i don't know if `animation` has events associated with it but i haven't came
across any sites breaking without them

~~~
myfonj
This is insightful remark; I guessed it could break some presumably crappy
designs blindly relying on transition-state or such, but … Google? Wow. Even
considering their approach to user level style sheets [1] it is mildly
surprising.

Side note: perhaps using `..duration: ..ms` in and `transition-timing-
function: step-start;` could make some additional micro optimisation.

[1] killed it:
[https://bugs.chromium.org/p/chromium/issues/detail?id=347016](https://bugs.chromium.org/p/chromium/issues/detail?id=347016)

------
iMuzz
On a slightly unrelated note: Can anyone recommend a good SVG animation course
that I could take. Or a set of guides that walk you through doing SVG
animations / typical workflows.

I took this[1] course over the weekend and didn't find it very helpful because
of a lack of code walkthroughs.

[1] - [https://www.lynda.com/Web-Development-tutorials/Advanced-
SVG...](https://www.lynda.com/Web-Development-tutorials/Advanced-SVG-
Animation/604272-2.html)

~~~
Fifer82
On a related note, are Lynda courses still absolutely dire?

------
andrenotgiant
My 2015 macbook pro will hit 150% CPU on basic SVG animation via CSS
properties (like rotating an SVG element by setting `transform:
rotate(90deg);`) even when using the best practices described in the article.

This means long, slow CSS animation absolutely kills browser performance.
Independent of your opinions on animation in the browser, is there a less CPU-
intensive way to do SVG animation?

~~~
kllrnohj
It's either just using SVG at all that's the problem or something in the SVG
that's a problem. SVGs are generally not GPU rasterized since GPUs are really
not built for paths. That's a whole research area in and of itself.

There are things you can attempt depending on your browser, though, such as
avoiding non-convex paths in the SVG.

If you want good performance everywhere though the only real option is just
don't use SVG if you need to animate it.

~~~
pcwalton
> SVGs are generally not GPU rasterized since GPUs are really not built for
> paths. That's a whole research area in and of itself.

It's not so much that GPUs aren't built for paths as that winding rules are
not suited for parallelism. The solution is to use meshes instead of paths.
This is my current area of work.

~~~
fulafel
Do you mean the non-zero rule and even-odd rules? In the WP definition they
don't inherently seem to have side effects or dependencies on previous
computations, can you link to an elaboration?

~~~
pcwalton
Computing whether a pixel is filled requires computing its winding number,
which depends on every path before it on the scanline. This is not a problem
for a sequential algorithm, since you compute winding numbers as you go, but
it is a problem if you want to fill every pixel in parallel.

------
amelius
I hope browser vendors take note and make this guide obsolete.

~~~
whowouldathunk
This guide will be relevant until OS compositors fundamentally change from
just dealing with bitmaps. Which is unlikely to happen anytime soon.

And doing UI layout on background threads breaks the basic design of pretty
much every UI framework, web or native, which are usually single-threaded.

~~~
pcwalton
> This guide will be relevant until OS compositors fundamentally change from
> just dealing with bitmaps. Which is unlikely to happen anytime soon.

There is absolutely no reason why browsers have to use the native compositor
for CSS. It's a bad fit, and browsers should stop doing it.

> And doing UI layout on background threads breaks the basic design of pretty
> much every UI framework, web or native, which are usually single-threaded.

That's why you have a render tree on a separate thread from the DOM. Look at
how Servo does it (disclaimer: I work on Servo). We've proven that it works.

~~~
jcelerier
> And doing UI layout on background threads breaks the basic design of pretty
> much every UI framework, web or native, which are usually single-threaded.

Dunno about the others but Qt has a threaded render loop
([http://doc.qt.io/qt-5/qtquick-visualcanvas-
scenegraph.html#t...](http://doc.qt.io/qt-5/qtquick-visualcanvas-
scenegraph.html#threaded-render-loop-threaded)) (and also has no problem
handling 1080p/60fps animations on embedded hardware)

~~~
pcwalton
> Dunno about the others but Qt has a threaded render loop
> ([http://doc.qt.io/qt-5/qtquick-visualcanvas-
> scenegraph.html#t...](http://doc.qt.io/qt-5/qtquick-visualcanvas-
> scenegraph.html#t...)) (and also has no problem handling 1080p/60fps
> animations on embedded hardware)

Largely written by Glenn Watson, the primary author of Servo's WebRender, no
less. :)

------
c-smile
Ideally so called rendering tree should reside completely on GPU. Or at least
all heavy rendering components that it represents shall be there.

In this case each animation frame will be just a set of commands sent by CPU
to GPU: render thing A at coordinate Ax,Ay, render thing B at ...

So animations that do not involve relayout will cost almost nothing for CPU.
And even with relayout ( transition: width 2s; ) it will not be that bad as
relayout is partial as a rule.

At least this is how it works in Sciter: [https://sciter.com/sciter-and-
directx/](https://sciter.com/sciter-and-directx/) (demo of Sciter HTML/CSS
rendering integrated into DirectX scene)

------
jhasse
Never buy a >= 120 Hz monitor. Everything else will start lagging :(

~~~
Double_a_92
I have one. Didn't notice any lagging. What are you talking about?

~~~
jhasse
I meant that after you're used to it, you'll start to notice "only" 60 FPS.
Also animations which are capped at 60 FPS will interpolate badly to 144 Hz.

But it isn't the case with the technique described in the article (browsers
also render with more than 60 FPS if the monitor refresh rate is higher), so
my comment was a bit offtopic, sorry.

------
distantsounds
"but the human eye can only see 30fps!"

~~~
xyzxyz998
Sarcasm doesn't carry well on the internet, if that was your intention (not
all of us know everything about everything). Please refrain, specially on this
board.

~~~
rootedbox
I can't actually tell if you are being sarcastic.. As he actually has a point.
If you're spending your time getting to make your hamburger work past 30 fps;
then you may need to rethink priorities.

~~~
Sohcahtoa82
For a simple web app, yeah, I'd agree that trying to get over 30 fps is
pointless, especially on mobile where I'll be concerned about battery usage.

But for gaming, anybody that can't tell the difference between 30 fps and 60
fps is blind. I have a 144 hz monitor, and I can certainly tell the difference
even between 60 fps and 144 fps.

The UFO Test [0], while contrived, will show you the difference. If you have a
60 hz monitor, it will show things moving at 60 fps and 30 fps (And 15 and 7.5
fps, if you want). If you have a 144 hz monitor, it will show 144 fps, 72 fps,
36 fps, etc. The difference is clear, especially if you're following the UFO
with your eyes. The higher framerate is less blurry. In games, this can be
huge.

[0]
[https://www.testufo.com/#test=framerates](https://www.testufo.com/#test=framerates)

~~~
dfshorty
It could be some kind of placebo effect, but I know the difference between 60
and 150+ fps even on 60hz screens. At least I'm sure I can feel it when
gaming.

~~~
Sohcahtoa82
It is 100% placebo because a 60 hz screen can only render 60 fps. If you're
getting 150 fps, then if you're playing with V-Sync enabled, only 2 of every 5
frames is being shown to you. The other three are being thrown out, never
reaching the monitor. If V-sync is disabled, then you're only seeing about
2/5ths of every frame with a tear in the screen when the next frame was shown,
causing rendered objects to shear.

------
luke3butler
TL;DR

These are the best css properties to animate with

Position — transform: translateX(n) translateY(n) translateZ(n);

Scale — transform: scale(n);

Rotation — transform: rotate(ndeg);

Opacity — opacity: n;

I'll add in that translate3d is generally faster than the other translate
options. There's some good performance info in the post and it's worth the
short read.

~~~
westoncb
They also point out that substantial performance gains are given by using
'will-change,' as in the following.

    
    
      .app-menu {
    	-webkit-transform: translateX(-100%);
    			transform: translateX(-100%);
    	transition: transform 300ms linear;
    	will-change: transform;

}

And I'd point out that the authors are specifically stating that animating
transform+opacity (via a 'transition') are more efficient than things like
left, top, bottom, etc.—because those properties affect the layout stage,
which is earlier than the composite stage (where the transform+opacity
properties operate), and subsequent stages have to be recalculated.

They also discuss different ways of structuring DOM trees to create the same
animation which have performance trade-offs.

~~~
luke3butler
Yep, the will-change was something new to me.

