useElementBounding
Tracks the bounding rect of a DOM element — x, y, top, right, bottom, left, width, height — as reactive Observable<number> values.
Uses ResizeObserver for size changes, MutationObserver for style/class attribute changes, and scroll/resize window events for position changes.
requestAnimationFrame is used by default so CSS transform animations are captured accurately.
import { function useRef$<T extends Element = Element>(externalRef?: React.Ref<T> | null): Ref$<T>
Creates an observable element ref. Can be used as a drop-in replacement for
useRef, composed with callback refs, or used with forwardRef.
The element is wrapped with opaqueObject to prevent legendapp/state
from making DOM properties reactive (deep observation).
useRef$, import useElementBounding
useElementBounding } from "@usels/core";
function function Component(): React.JSX.Element
Component() { const const el$: Ref$<HTMLDivElement>
el$ = useRef$<HTMLDivElement>(externalRef?: React.Ref<HTMLDivElement> | undefined): Ref$<HTMLDivElement>
Creates an observable element ref. Can be used as a drop-in replacement for
useRef, composed with callback refs, or used with forwardRef.
The element is wrapped with opaqueObject to prevent legendapp/state
from making DOM properties reactive (deep observation).
useRef$<interface HTMLDivElement
HTMLDivElement>(); const { const top$: any
top$, const left$: any
left$, const width$: any
width$, const height$: any
height$ } = import useElementBounding
useElementBounding(const el$: Ref$<HTMLDivElement>
el$);
return ( <React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div React.RefAttributes<HTMLDivElement>.ref?: React.Ref<HTMLDivElement> | undefined
Allows getting a ref to the component instance.
Once the component unmounts, React will set ref.current to null
(or call the ref with null if you passed a callback ref).
ref={const el$: Ref$<HTMLDivElement>
el$}> {const width$: any
width$.any
get()} × {const height$: any
height$.any
get()} at ({const left$: any
left$.any
get()}, {const top$: any
top$.any
get()}) </React.JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> );}Manual update
Section titled “Manual update”const { const top$: any
top$, const left$: any
left$, const update: any
update } = import useElementBounding
useElementBounding(const el$: Ref$<HTMLDivElement>
el$);
// Force-recalculate bounding rect imperativelyconst update: any
update();Disable window scroll tracking
Section titled “Disable window scroll tracking”const { top$, left$ } = useElementBounding(el$, { windowScroll: false });Skip requestAnimationFrame (synchronous reads)
Section titled “Skip requestAnimationFrame (synchronous reads)”const { width$, height$ } = useElementBounding(el$, { useCssTransforms: false });Keep values on unmount (no reset)
Section titled “Keep values on unmount (no reset)”const { top$ } = useElementBounding(el$, { reset: false });Type Declarations
Section titled “Type Declarations”export interface UseElementBoundingOptions { reset?: boolean; windowResize?: boolean; windowScroll?: boolean; immediate?: boolean; useCssTransforms?: boolean;}export interface UseElementBoundingReturn { x$: Observable<number>; y$: Observable<number>; top$: Observable<number>; right$: Observable<number>; bottom$: Observable<number>; left$: Observable<number>; width$: Observable<number>; height$: Observable<number>; update: () => void;}export declare function useElementBounding(target: MaybeElement, options?: DeepMaybeObservable<UseElementBoundingOptions>): UseElementBoundingReturn;Source
Section titled “Source”Contributors
Section titled “Contributors”- tigerwest
Changelog
Section titled “Changelog”a7392ab2026-03-06 - feat(core,browser): add sync strategy hooks (tigerwest)