Can we animate the width or height properties of an element without causing expensive reflows, in order to reveal or open a menu? If so, how? An alternate question might be: can animation of width/height be hardware accelerated by the GPU in certain cases?
EDIT: Changed the title from “Animating CSS width/height without performance loss from reflow?” to “Hardware accelerated animation of CSS width/height”.
If hardware acceleration is not possible, that’d be an nice thing to add to browsers. For example, when no element in a parent container ever need to reflow when the parent is re-sized, then it’d be nice for the resize animation to go to the GPU.
AFAIK, scale transforms are efficient to animate. They don’t change the element’s layout size though, they just stretch the way it’s drawn, which is why they are fast. If you need it up update the layout size, then you can’t avoid the expensive reflows.
Scale can be hardware accelerated, but it doesn’t help with dynamic dimension elements so much.
ie - we have to apply some css class, measure the height of the element, remove the class, then apply a style attribute which can be transitioned. This all happens inside the browser lifecycle, as far as I understand it - meaning that it is possible to measure an element, then before the paint happens, remove the class, apply the new styles and let the browser perform its paint cycle.
This is all a bit … fiddly!
I was looking at some techniques for doing this on a codepen - might be interesting for you too.
Two controls, click on ‘promised’ for a promise based measure / paint, and rAF for a reqAnimFrame approach.
I don’t need it to update the layout. The element that I’m animating width and height of contains elements inside that are absolutely positioned and don’t change size. The elements inside are clipped by the animated container’s overflow:hidden property. So basically, while I animate the container open, it reveals the content inside of it. I find that this works fine on Desktop, but is jank on my Nexus 5.
I’m guessing that, although I’m probably animating the width and height in the best way possible (i.e. it doesn’t cause any elements inside of it to reflow since the inner elements have constant size and are absolutely positioned), that it just simply isn’t a hardware accelerated animation, and it still runs on the main CPU? Do you think that’s the case?
CSS Layout Containment will allow browser engines to perform an optimization which means that it’ll only reflow the subtree which you are changing. (which should reduce jank in the future).
(you may already be hitting this “layout boundary” optimization with overflow:hidden on the parent on certain browsers).
It seems to me that if no reflow will happen that the browser should detect that, and do the clipping on the GPU (as in my case). I’ve got nothing to contain in my case as everything in the container is absolutely positioned and the container has overflow:hidden (slightly different than clip) but there’s nothing in there that will reflow when I animate the container’s width and height.
I think it makes sense for a browser to detect that case draw the simple case with the GPU.