get dimensions of element without waiting for "recalculate style"

Viewed 63

I am working on improving performance of some graphics intensive code, and one of the bottlenecks is that it sometimes needs to get the dimensions of a certain div. Most of the time this is fine, but occasionally it gets stuck for ~100ms waiting for the style to be recalculated.

Normally, I understand that we need to wait for the style to recalculate so that the dimensions returned are accurate, but this is causing it to pause for 100ms in the middle of an animation. I am okay with inaccurate or out of date metrics, as long as I can get them quickly. I don't want to pause everything to recalculate the style.

Is there any way to avoid waiting for this recalculated style?

To summarize my use case: I am performing animations inside a canvas (with PIXI if anyone cares). The elements inside the canvas are arranged in rows that match up with HTML rows outside the canvas. Every time a canvas row is redrawn, we need to fetch the position and height of the external HTML row to figure out the height and top offset of the canvas row.

The HTML rows can change position and height, so the canvas rows need to be able to react to this. However, even when the HTML rows are not changing position or height, my canvas painting can get hung up for 100+ms waiting for a "recalculate style" to finish so that it can figure out it's height and top offsets. I'm perfectly happy if it's a little laggy when the rows change position and height (since it shouldn't happen too often), but it shouldn't mess up every animation of the rows contents to this extent.

EDIT: Just want to add that unconventional, hacky, or complex solutions are both expected and appreciated. I understand that this is not necessarily a question that can be answered with a one-liner.

1 Answers

The issue is that even if your code doesn't trigger these reflows they will anyway get triggered by the next repaint.

So you could indeed avoid triggering these from your code by caching the results, for instance from a ResizeObserver, or if you target old browsers simply by waiting after the next paint (requestAnimationFrame(() => setTimeout(cacheDimensions, 0));), but since you are not responsible for the layout trashing, you will always have the 100ms spent on calculating the new layout that will eat your animation time anyway.

100ms for a recalc is huge, so instead I invite you to find out what in your layout makes this recalc so complex and find a way to isolate the layer that needs update.

Related