observeElementResize
Observes an element for size changes using ResizeObserver.
1/**
2 * Observes an element for size changes using ResizeObserver.
3 *
4 * @param element - The target element to observe.
5 * @param callback - Function called with the element when resized.
6 * @returns A cleanup function to stop observing.
7 */
8export function observeElementResize(
9 element: Element,
10 callback: (el: Element) => void
11): () => void {
12 const observer = new ResizeObserver(entries => {
13 for (const entry of entries) {
14 if (entry.target === element) {
15 callback(entry.target);
16 }
17 }
18 });
19
20 observer.observe(element);
21
22 return () => observer.disconnect();
23}
Modern Resize Detection
Leverages
ResizeObserver
, a performant and efficient way to detect element size changes without polling.Precise Target Handling
Ensures only the specified element triggers the callback, even if multiple elements are observed.
Lightweight Cleanup
Returns a simple cleanup function (
() => observer.disconnect()
) to stop observing and prevent memory leaks.Efficient and Non-Intrusive
Operates asynchronously and off the main thread, minimizing performance overhead during layout changes.
Tests | Examples
1let observeMock: jest.Mock;
2let disconnectMock: jest.Mock;
3
4beforeEach(() => {
5 observeMock = jest.fn();
6 disconnectMock = jest.fn();
7
8 (global as any).ResizeObserver = jest.fn(() => ({
9 observe: observeMock,
10 disconnect: disconnectMock,
11 }));
12});
13
14test('observes the given element', () => {
15 const element = document.createElement('div');
16 const callback = jest.fn();
17
18 const stop = observeElementResize(element, callback);
19
20 expect(observeMock).toHaveBeenCalledWith(element);
21 stop();
22 expect(disconnectMock).toHaveBeenCalled();
23});
24
25test('triggers callback on resize entry matching target', () => {
26 const element = document.createElement('div');
27 const callback = jest.fn();
28
29 let internalCallback: (entries: ResizeObserverEntry[]) => void = () => {};
30 (global as any).ResizeObserver = jest.fn(cb => {
31 internalCallback = cb;
32 return {
33 observe: jest.fn(),
34 disconnect: jest.fn(),
35 };
36 });
37
38 observeElementResize(element, callback);
39 internalCallback([{ target: element }] as ResizeObserverEntry[]);
40
41 expect(callback).toHaveBeenCalledWith(element);
42});
Common Use Cases
Responsive Component Layouts
Adjust layout or UI logic dynamically based on container size changes (e.g. card resizing, adaptive charts).
Dynamic UI Elements
Monitor elements whose size may change due to content updates, user actions, or CSS transitions.
Custom Scroll Containers
React to size changes in scrollable areas to adjust scrollbars or layout padding.
Media or Image Containers
Trigger logic when embedded media or images cause layout shifts due to size changes.
Interactive Drag-Resize Interfaces
Recalculate layout or constraints in response to manual resizing actions in UI widgets.