useElementVisibility
Tracks whether a DOM element is visible within the viewport (or a specified scroll container).
Returns a reactive Observable<boolean> that updates automatically via the IntersectionObserver API.
All option values accept either a plain value or an Observable<T>.
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$, type Ref$<T> = ((node: T | null) => void) & { get(): OpaqueObject<T> | null; peek(): OpaqueObject<T> | null;}
Ref$, import useElementVisibility
useElementVisibility } 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 isVisible$: any
isVisible$ = import useElementVisibility
useElementVisibility(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$} />;}With initial value
Section titled “With initial value”const const isVisible$: any
isVisible$ = import useElementVisibility
useElementVisibility(const el$: Ref$<HTMLDivElement>
el$, { initialValue: boolean
initialValue: true });Stop after first visible
Section titled “Stop after first visible”Use once: true to automatically stop observing after the element becomes visible for the first time:
const const isVisible$: any
isVisible$ = import useElementVisibility
useElementVisibility(const el$: Ref$<HTMLDivElement>
el$, { once: boolean
once: true });Custom scroll container
Section titled “Custom scroll container”Pass a scrollTarget to observe intersection within a scrollable container instead of the viewport:
const const container$: Ref$<HTMLDivElement>
container$ = 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 isVisible$: any
isVisible$ = import useElementVisibility
useElementVisibility(const el$: Ref$<HTMLDivElement>
el$, { scrollTarget: Ref$<HTMLDivElement>
scrollTarget: const container$: Ref$<HTMLDivElement>
container$ });Threshold and rootMargin
Section titled “Threshold and rootMargin”const const isVisible$: any
isVisible$ = import useElementVisibility
useElementVisibility(const el$: Ref$<HTMLDivElement>
el$, { threshold: number
threshold: 0.5, rootMargin: string
rootMargin: "0px 0px -100px 0px",});Reactive options
Section titled “Reactive options”All options accept Observable<T> for reactive control:
const const threshold$: any
threshold$ = observable<number | {}>(value: Promise<number | {}> | (() => number | {}) | (number | {})): any (+2 overloads)
observable<number | number[]>(0.5);const const rootMargin$: any
rootMargin$ = observable<unknown>(value: Promise<unknown> | (() => unknown) | unknown): any (+2 overloads)
observable("0px");const const once$: any
once$ = observable<unknown>(value: Promise<unknown> | (() => unknown) | unknown): any (+2 overloads)
observable(false);
const const isVisible$: any
isVisible$ = import useElementVisibility
useElementVisibility(const el$: Ref$<HTMLDivElement>
el$, { threshold: any
threshold: const threshold$: any
threshold$, rootMargin: any
rootMargin: const rootMargin$: any
rootMargin$, once: any
once: const once$: any
once$,});
// later — update reactivelyconst threshold$: any
threshold$.any
set(0.75);const rootMargin$: any
rootMargin$.any
set("-50px 0px");Type Declarations
Section titled “Type Declarations”export interface UseElementVisibilityOptions { initialValue?: boolean; scrollTarget?: MaybeElement; rootMargin?: string; threshold?: number | number[]; once?: boolean;}export declare function useElementVisibility(element: MaybeElement, options?: DeepMaybeObservable<UseElementVisibilityOptions>): Observable<boolean>;Source
Section titled “Source”Contributors
Section titled “Contributors”- tigerwest
Changelog
Section titled “Changelog”a7392ab2026-03-06 - feat(core,browser): add sync strategy hooks (tigerwest)