Product media placeholder
Replace this area with a screenshot or short walkthrough video during the media sweep.
IntersectionObserver-backed visibility detector. Watches a single element (typically per-clone in a forEach template via `{ "fromScope": "selector" }`) and emits an `enterPulse` (single frame) when it becomes visible, an `exitPulse` when it leaves, plus a continuous `isVisible` gate and the raw `intersectionRatio` (0..1). Crucially this fires on transform-induced visibility changes too — a translateX-driven carousel (no document scroll) still triggers the pulses, which is what differentiates it from `scrollTrigger`'s scroll-event-driven progress. Use as the trigger for per-card pluck animations: each card's pluck fires the moment IT enters view, with parameters captured from a velocity signal at that exact moment via a `latch`.
Inputs
| Port | Type | Description |
|---|---|---|
| - | - | No ports declared. |
Outputs
| Port | Type | Description |
|---|---|---|
enterPulse | float | Single-frame `1` on each visibility-enter (intersectionRatio crosses up through `threshold`), `0` otherwise. |
exitPulse | float | Single-frame `1` on each visibility-exit, `0` otherwise. |
isVisible | float | `1` while element is past `threshold`, `0` otherwise. Use as a gate. |
intersectionRatio | float | Raw intersection ratio 0..1. Useful as a falloff signal for in-view animations (e.g. opacity = ratio). |
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
selector | elementSelector | "" | CSS selector for the element to observe. Inside a forEach template, set this to `{ "fromScope": "selector" }` for per-iteration matched elements. |
rootMargin | string | "0px" | CSS-style margin that expands or contracts the viewport rect for the intersection test. `0px` = actual viewport. `-50px` = fire only when element is 50px inside. `200px` = fire 200px BEFORE visible (preload). |
threshold | float | 0.05 | Visibility ratio that flips the gate. 0.05 = "any sliver visible" (default — fires as soon as leading edge enters). 0.5 = "majority visible". 1.0 = "fully visible". min 0.01; max 1; step 0.05 |
Use cases
- Per-card pluck on entry — forEach `{ fromScope: "selector" }` per card → viewportObserver → enterPulse → latch(velocity) → tween a swing-out + elastic-return rotation. Each card animates on its own clock because each enters the viewport at a different moment during a drag.
- Lazy reveal — fire a one-shot animation when a section first becomes visible. enterPulse → pulseTween → propertyAnimation.
- Off-screen disable — `isVisible` gates a heavy animation node's `gateInput` so it does no work when scrolled out of view.
Related nodes
Envelope
Use viewportObserver as the node type inside a graph node envelope. Add id, optional params, optional connections, and optional activeWhen based on the guide context.
Generated source
Registry faster-motion-docs/node-registry.jsonCategory page /help/faster-motion/faster-motion-node-category-inputs/