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.
Peeke Kuepers
source share