IntersectionObserver
getIntersectionObserver(options) returns an IntersectionObserver keyed by its options — every
target that asks for the same root, rootMargin and threshold shares one underlying observer, so
a page full of lazy images or reveal triggers stays cheap. It’s the primitive that powers
InView; reach for it directly when you want raw intersection data.
Outside
0%
scroll down ↓
observed target
↑ scroll back up
Outside
0%
scroll down ↓
observed target
↑ scroll back up
Scroll inside the panel — the target is observed against the panel as its root, so the ratio
bar tracks intersectionRatio live.
Usage
import { useEffect, useRef, useState } from 'react';
import { getIntersectionObserver } from '@60fps/utils';
function Tracked() {
const ref = useRef<HTMLDivElement>(null);
const [visible, setVisible] = useState(false);
useEffect(() => {
const el = ref.current;
if (!el) return;
const io = getIntersectionObserver({ threshold: 0.5 });
const onIntersect = (entry: IntersectionObserverEntry) => setVisible(entry.isIntersecting);
io.subscribe(el, onIntersect);
return () => io.unsubscribe(el, onIntersect);
}, []);
return <div ref={ref}>{visible ? 'visible' : 'hidden'}</div>;
}
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import { getIntersectionObserver } from '@60fps/utils';
const el = ref<HTMLElement | null>(null);
const visible = ref(false);
const io = getIntersectionObserver({ threshold: 0.5 });
const onIntersect = (entry: IntersectionObserverEntry) => (visible.value = entry.isIntersecting);
onMounted(() => el.value && io.subscribe(el.value, onIntersect));
onUnmounted(() => el.value && io.unsubscribe(el.value, onIntersect));
</script>
<template>
<div ref="el">{{ visible ? 'visible' : 'hidden' }}</div>
</template>
API
getIntersectionObserver(options?, polyfill?)
| Option | Type | Default | Description |
|---|---|---|---|
root | Element | Document | null | null | The viewport ancestor to test against. `null` is the browser viewport. |
rootMargin | string | '0px' | Margin grown/shrunk around the root before computing intersections. |
threshold | number | number[] | 0 | Ratio(s) of visibility at which the callback fires. |
The returned manager mirrors the ResizeObserver one:
| Member | Type | Default | Description |
|---|---|---|---|
subscribe(el, cb) | (Element, cb) => void | — | Observe an element; the callback receives its IntersectionObserverEntry. |
unsubscribe(el, cb) | (Element, cb) => void | — | Remove a callback; the element is unobserved once its last callback is gone. |
observer | IntersectionObserver | — | The underlying shared observer instance. |