Skip to content
Elements

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.

Element Bounding

Resize the box below to see its bounding rect update.

x
0px
y
0px
top
0px
left
0px
width
0px
height
0px
resize me ↘
import {
const useRef$: {
<T = any>(initialValue: null): Ref$<T | null>;
<T = any>(initialValue: T): Ref$<T>;
<T = any>(): Ref$<T | null>;
}
useRef$
} from "@usels/core";
import {
const useElementBounding: (target: MaybeEventTarget, options?: DeepMaybeObservable<UseElementBoundingOptions>) => UseElementBoundingReturn
useElementBounding
} from "@usels/web";
function
function Component(): JSX.Element
Component
() {
const
const el$: Ref$<HTMLDivElement | null>
el$
=
useRef$<HTMLDivElement>(): Ref$<HTMLDivElement | null> (+2 overloads)

Core (framework-agnostic) version of useRef$. Creates an observable element ref with opaque wrapping.

  • non-null value → Ref$<T>: current, get(), peek() return T
  • null / no arg → Ref$<T | null>: current, get(), peek() return T | null

Nullability is expressed via the type parameter, mirroring T | null at the call site.

useRef$
<
interface HTMLDivElement
HTMLDivElement
>();
const {
const top$: any
top$
,
const left$: any
left$
,
const width$: any
width$
,
const height$: any
height$
} =
function useElementBounding(target: MaybeEventTarget, options?: DeepMaybeObservable<UseElementBoundingOptions>): UseElementBoundingReturn

Framework-agnostic bounding-rect tracker. Must be called inside a useScope factory — ResizeObserver / MutationObserver / window listeners are registered via the scope-aware create* helpers and are cleaned up automatically when the scope disposes. Public API matches the legacy useElementBounding hook.

useElementBounding
(
const el$: Ref$<HTMLDivElement | null>
el$
);
return (
<
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
RefAttributes<HTMLDivElement>.ref?: 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 | null>
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
()})
</
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>
);
}
// @noErrors
import { useRef$, Ref$ } from "@usels/core";
import { useElementBounding } from "@usels/web";
declare const el$: Ref$<HTMLDivElement>;
// ---cut---
const { top$, left$, update } = useElementBounding(el$);
// Force-recalculate bounding rect imperatively
update();
const { top$, left$ } = useElementBounding(el$, { windowScroll: false });

Skip requestAnimationFrame (synchronous reads)

Section titled “Skip requestAnimationFrame (synchronous reads)”
const { width$, height$ } = useElementBounding(el$, { useCssTransforms: false });
const { top$ } = useElementBounding(el$, { reset: false });
ParameterTypeDescription
targetMaybeEventTarget-
optionsUseElementBoundingOptions (optional)-
OptionTypeDefaultDescription
resetboolean-Reset all values to 0 when element unmounts. Default: true
windowResizeboolean-Re-calculate on window resize. Default: true
windowScrollboolean-Re-calculate on window scroll. Default: true
immediateboolean-Calculate immediately on mount. Default: true
useCssTransformsboolean-Use requestAnimationFrame to read rect after CSS transforms settle. Default: true
windowWindowSource--

UseElementBoundingReturn

NameTypeDescription
x$ObservablePrimitive<number>-
y$ObservablePrimitive<number>-
top$ObservablePrimitive<number>-
right$ObservablePrimitive<number>-
bottom$ObservablePrimitive<number>-
left$ObservablePrimitive<number>-
width$ObservablePrimitive<number>-
height$ObservablePrimitive<number>-
update() => void-

View on GitHub