svelte-intersection-observer
Detect if an element is in the viewport using the Intersection Observer API.
Try it in the Svelte REPL.
Table of Contents
Installation
# NPM npm i svelte-intersection-observer # pnpm pnpm i svelte-intersection-observer # Bun bun i svelte-intersection-observer # Yarn yarn add svelte-intersection-observer
Usage
Basic
Use the bind:this
directive to pass an element reference to the IntersectionObserver
component.
Then, simply bind to the reactive intersecting
prop to determine if the element intersects the viewport.
<script> import IntersectionObserver from "svelte-intersection-observer"; let element; let intersecting; </script> <header class:intersecting> {intersecting ? "Element is in view" : "Element is not in view"} </header> <IntersectionObserver {element} bind:intersecting> <div bind:this={element}>Hello world</div> </IntersectionObserver>
Once
Set once
to true
for the intersection event to occur only once. The element
will be unobserved after the first intersection event occurs.
<script> import IntersectionObserver from "svelte-intersection-observer"; let elementOnce; let intersectOnce; </script> <header class:intersecting={intersectOnce}> {intersectOnce ? "Element is in view" : "Element is not in view"} </header> <IntersectionObserver once element={elementOnce} bind:intersecting={intersectOnce} > <div bind:this={elementOnce}>Hello world</div> </IntersectionObserver>
let:intersecting
An alternative to binding to the intersecting
prop is to use the let:
directive.
In the following example, the “Hello world” element will fade in when its containing element intersects the viewport.
<script> import IntersectionObserver from "svelte-intersection-observer"; import { fade } from "svelte/transition"; let node; </script> <header /> <IntersectionObserver element={node} let:intersecting> <div bind:this={node}> {#if intersecting} <div transition:fade={{ delay: 200 }}>Hello world</div> {/if} </div> </IntersectionObserver>
on:observe
event
The observe
event is dispatched when the element is first observed and also whenever an intersection event occurs.
<IntersectionObserver {element} on:observe={(e) => { console.log(e.detail); // IntersectionObserverEntry console.log(e.detail.isIntersecting); // true | false }} > <div bind:this={element}>Hello world</div> </IntersectionObserver>
on:intersect
event
As an alternative to binding the intersecting
prop, you can listen to the intersect
event that is dispatched if the observed element is intersecting the viewport.
Note: Compared to on:observe
, on:intersect
is dispatched only when the element is intersecting the viewport. In other words, e.detail.isIntersecting
will only be true
.
<IntersectionObserver {element} on:intersect={(e) => { console.log(e.detail); // IntersectionObserverEntry console.log(e.detail.isIntersecting); // true }} > <div bind:this={element}>Hello world</div> </IntersectionObserver>
API
Props
Name | Description | Type | Default value |
---|---|---|---|
element | Observed element | HTMLElement |
null |
once | Unobserve the element after the first intersection event | boolean |
false |
intersecting | true if the observed element is intersecting the viewport |
boolean |
false |
root | Containing element | null or HTMLElement |
null |
rootMargin | Margin offset of the containing element | string |
"0px" |
threshold | Percentage of element visibile to trigger an event | number between 0 and 1, or an array of number s between 0 and 1 |
0 |
entry | Observed element metadata | IntersectionObserverEntry |
null |
observer | IntersectionObserver instance |
IntersectionObserver |
null |
Dispatched events
- on:observe: fired when the element is first observed or whenever an intersection change occurs
- on:intersect: fired when the element is intersecting the viewport
The e.detail
dispatched by the observe
and intersect
events is an IntersectionObserverEntry
interface.
Note that all properties in IntersectionObserverEntry
are read-only.
IntersectionObserverEntry
interface IntersectionObserverEntry { target: HTMLElement; time: number; isIntersecting: boolean; isVisible: boolean; intersectionRatio: number; intersectionRect: { bottom: number; height: number; left: number; right: number; top: number; width: number; x: number; y: number; }; rootBounds: { bottom: number; height: number; left: number; right: number; top: number; width: number; x: number; y: number; }; boundingClientRect: { bottom: number; height: number; left: number; right: number; top: number; width: number; x: number; y: number; }; }