Hooks
useIntersectionObserver
Observe whether an element intersects the viewport (or a custom root) via IntersectionObserver, with automatic cleanup.
Returns reactive isIntersecting for simple cases, or accepts a callback for full entry access.
The target may be a reactive getter. SSR-safe.
Basic visibility
Read io.isIntersecting directly - no callback needed.
Not visible
<script lang="ts">
import { useIntersectionObserver } from 'sv5ui';
let el = $state<HTMLDivElement>();
const io = useIntersectionObserver(() => el);
</script>
<div bind:this={el} class="rounded border p-6 text-center">
{io.isIntersecting ? 'Visible in viewport' : 'Not visible'}
</div>Lazy reveal
Use rootMargin to trigger the callback before the element enters the viewport. Ideal for lazy-loading images or infinite scroll.
Scroll into view to reveal
<script lang="ts">
import { useIntersectionObserver } from 'sv5ui';
let img = $state<HTMLImageElement>();
let loaded = $state(false);
useIntersectionObserver(
() => img,
(entry) => {
if (entry.isIntersecting && !loaded) {
loaded = true;
}
},
{ rootMargin: '200px' } // start loading 200px before entering viewport
);
</script>
<img
bind:this={img}
src={loaded ? '/real-image.jpg' : undefined}
alt="Lazy loaded"
class="h-48 w-full rounded object-cover bg-surface-container"
/>Threshold & rootMargin
Pass threshold to fire at specific intersection ratios (0–1), and rootMargin to shrink or grow the root's effective bounding box.
See code - logs intersectionRatio to console.
<script lang="ts">
import { useIntersectionObserver } from 'sv5ui';
let el = $state<HTMLDivElement>();
useIntersectionObserver(
() => el,
(entry) => {
console.log('ratio:', entry.intersectionRatio);
},
{
threshold: [0, 0.25, 0.5, 0.75, 1], // fire at each 25% step
rootMargin: '-10% 0px' // shrink root by 10% top/bottom
}
);
</script>
<div bind:this={el} class="h-32 rounded border p-4">Scroll to observe</div>Parameters
| Parameter | Type | Default |
|---|---|---|
target | Element | (() => Element | null) | null | - |
callback | (entry: IntersectionObserverEntry) => void | undefined |
options | IntersectionObserverInit | undefined |
Return
| Property | Type | Default |
|---|---|---|
isIntersecting | boolean | false |