An event or observer for changes to getBoundingClientRect()
As mentioned in the comments above. The APIs you're looking for are: ResizeObserver
and IntersectionObserver
. However, there are a few things to note:
ResizeObserver
will only fire when the observed element changes size. And it will essentially only give you correct values for width and height.- Both
ResizeObserver
andIntersectionObserver
are supposed to not block paint ResizeObserver
will trigger after layout but before paint, which essentially makes it feel synchronous.IntersectionObserver
fires asynchronously.
What if you need position change tracking
This is what IntersectionObserver
is made for. It can often be used for visibility detection. The problem here is that IntersectionObserver
only fires when the ratio of intersection changes. This means that if a small child moves around within a larger container div, and you track intersection between the parent and the child, you won't get any events except when the child is entering or exiting the parent.
You can still track when an element moves at all. This is how:
- Start by measuring the position of the element you want to track using
getBoundingClientRect
. - Insert a div as an absolutely positioned direct child of body which is positioned exactly where the tracked element is.
- Start tracking the intersection between this div and the original element.
- The intersection should start at 1. Whenever it changes to something else:
- Remeasure the element using
getBoundingClientRect
. - Fire the position/size changed event
- update the styles of the custom div to the new position of the element.
- the observer should fire again with the intersection ratio at 1 again, this value can be ignored.
- Remeasure the element using
NOTE: this technique can also be used for more efficient polypill for ResizeObserver
which is a newer feature than IntersectionObserver
. The commonly available polyfills rely on MutationObserver
which is considerably less efficient.