Change CSS3 transform without starting style recount?

Trying to animate an element with absolute positioning on the screen at 60FPS, I noticed that most processor time is used by recaculateStyles .

Is it possible to change the element.style.transform property without starting the style recount?

Currently, I am changing the position like this: el.style.transform = 'translate3d(${x}px, ${y}px, 0px)' ;

Here's a demo: http://jsfiddle.net/pLtvxv41/ You can use the Google Chrome performance developer tool to see the use of the recalculateStyle function.

Can this be changed in a more efficient way?

enter image description here

+7
performance javascript css browser css3
source share
2 answers

I recently came across this myself, and I was very surprised by the behavior of the browsers. It seems that I am just setting the transform (or opacity for that matter), should not cause a recount of style. After breaking my brains for several hours, I finally found a fix.

It turns out that using the web animation API, you can apply transformation styles without calling recalc:

 const styles = { transform: 'translateX(100%)' } element.animate([styles, styles], {duration: 1}).pause() 

Edit: Recounting is still happening, it seems to be happening more efficiently. In my case, the elapsed time fell from 90 ms per frame to 7 ms.

This initializes the web animation with the styles we want at the beginning and end of the frame, and then pauses the animation. { duration: 1 } necessary because the animation will not work if it is 0 (which is the default value). We need to enter styles twice because a timeline with at least two keyframes is expected.

I wrapped it in this helper to provide backward compatibility:

 const dirtyApplyStyles = (element, styles) => { if (!('animate' in element)) { Object.assign(element.style, styles) return } const styles = { transform: 'translateX(100%)' } element.animate([styles, styles], {duration: 1}).pause() } 

If anyone has any other way to apply styles without recounting, please let me know. Because this decision is obviously a bit hacked.

+2
source share

You tried to add -webkit-transform: translate3d(0,0,0); by default to avoid a complete redraw of the page?

You can also try the will-change behavior to tell the browser that the conversion property will be changed

 .example { will-change: transform; } 
0
source share

All Articles