Help guide

Viewport Observer node

Updated June 21, 2026

Viewport Observer node

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`.

Type viewportObserverCategory inputsContext sharedDynamic ports noCompound no

Inputs

PortTypeDescription
--No ports declared.

Outputs

PortTypeDescription
enterPulsefloatSingle-frame `1` on each visibility-enter (intersectionRatio crosses up through `threshold`), `0` otherwise.
exitPulsefloatSingle-frame `1` on each visibility-exit, `0` otherwise.
isVisiblefloat`1` while element is past `threshold`, `0` otherwise. Use as a gate.
intersectionRatiofloatRaw intersection ratio 0..1. Useful as a falloff signal for in-view animations (e.g. opacity = ratio).

Parameters

ParameterTypeDefaultDescription
selectorelementSelector""CSS selector for the element to observe. Inside a forEach template, set this to `{ "fromScope": "selector" }` for per-iteration matched elements.
rootMarginstring"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).
thresholdfloat0.05Visibility 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/

Was this guide helpful?

Sunny Arora

Written by

Sunny Arora

Get technical deep dives delivered to your inbox

Join creators and developers who get exclusive insights, tutorials, and behind-the-scenes content every week.

No spam. Unsubscribe anytime.

Continue Exploring

You might also enjoy