useIntersectionObserver#

Observe viewport intersection with an IntersectionObserver. Browser composable — import from @sigx/use-web.

The observer follows reactive targets, supports pause()/resume() without losing its config, and disconnects with the owning scope. Point it at a single element target or an array.

TypeScript
import { signal } from 'sigx';
import { useIntersectionObserver } from '@sigx/use-web';

const sentinel = signal<HTMLElement | null>(null);
// <div ref={sentinel}> …

useIntersectionObserver(sentinel, ([entry]) => {
    if (entry.isIntersecting) loadMore();
});

The callback is the native IntersectionObserverCallback — you get IntersectionObserverEntry[]. Configure root (an element target or Document), rootMargin, and threshold as with the native observer.

Just need a reactive "is it on screen?" boolean? Use useElementVisibility, which wraps this.

Signature#

TypeScript
function useIntersectionObserver(
    target: MaybeSignalElement | MaybeSignalElement[],
    callback: IntersectionObserverCallback,
    options?: UseIntersectionObserverOptions,
): UseIntersectionObserverReturn;

Options#

OptionTypeDefaultDescription
rootMaybeSignalElement | DocumentviewportIntersection root to observe within.
rootMarginstring'0px'Margin around the root (native rootMargin).
thresholdnumber | number[]0Visibility ratio(s) that trigger the callback.
immediatebooleantrueStart observing on creation.
windowWindowdefaultWindowOverride the window (SSR/testing).

Returns#

TypeScript
interface UseIntersectionObserverReturn extends Pausable {
    isSupported: ReadSignal<boolean>;
    stop: Stop;
}

Extends Pausable (isActive, pause, resume) with isSupported and a stop that disconnects the observer.

SSR#

Inert: on the server or where IntersectionObserver is unavailable, isSupported is false and the observer never runs.

See also#