Skip to content

Viewport Detection

useLazyLoad(options?) is the low-level IntersectionObserver composable useImage() is built on. Exposed directly for anything that needs plain "has this element entered the viewport yet" state without the rest of useImage's loading state machine.

ts
import { useLazyLoad } from '@macrulez/vue-image-kit'

const { isIntersecting, observe } = useLazyLoad({ rootMargin: '300px' })

Options

rootMargin

string · default: '200px'. IO rootMargin.

threshold

number · default: 0. IO threshold.

Return value

isIntersecting

Ref<boolean>. true once the observed element has entered the viewport (per rootMargin/threshold). Stays true after the first intersection — the observer disconnects itself once triggered, this is a one-shot "has it appeared yet" signal, not a continuous visibility tracker.

observe

(el: Ref<HTMLElement | null>) => void. Starts watching an element. Safe to call in setup() before the element is mounted — if the ref isn't populated yet, watching is deferred to the next microtask automatically. Calling observe again with a new element tears down the previous observer first.

On the server, isIntersecting starts (and stays) true and observe() is a no-op — this is what makes SSR output render as "already visible" instead of waiting on an API that doesn't exist server-side. Both useImage() and useBackgroundImage() call this composable directly for their own viewport detection. The v-lazy-img directive follows the same SSR contract but implements its own IntersectionObserver logic separately (a directive can't call a composable).