Product media placeholder
Replace this area with a screenshot or short walkthrough video during the media sweep.
Batched per-element stagger writer, multi-channel. One node animates N CSS properties across the elements matching a selector, with a shared per-element stagger window. F358: each property is one channel in the `channels` map — add as many as you want (e.g. `rotateX` + `color` + `opacity`) and they all share the same selector, totalStagger, staggerOrder, and progress driver. Replaces the older "two staggerWrites with the same selector and one property each" pattern with a single node.
Inputs
| Port | Type | Description |
|---|---|---|
progress | float | Single 0..1 driver. Each matched element gets a window inside this range — every channel's `from → to` interpolation runs across the element's own slice (size = 1 − totalStagger). Wire from a `timeline.progress`, `scrollTrigger.progress`, `phaseShift.value`, or any normalized signal. |
selector | string | F357 — wireable selector. When connected to an upstream string source (typically `splitText.pieceSelector`), the wired value overrides the `CSS Selector` param at bind time. Unwired = the param value is used. |
Outputs
| Port | Type | Description |
|---|---|---|
| - | - | No ports declared. |
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
selector | elementSelector | "" | CSS selector matching the elements to animate. Pair with `splitText` upstream — its emitted spans use `.ft-split-char` / `.ft-split-word` / `.ft-split-line` selectors. For lists / grids, point at a class like `.list-item`. All matched elements are batched into one accumulator pass. |
channels | staggerChannels | {} | Map of CSS property → channel config. Each channel has `{ from, to, cssUnit?, ease?, template? }` — one entry per property you want to drive. All channels share this node's selector + stagger window + progress, so adding a channel costs 0 graph nodes (vs. authoring a second staggerWrite). Property names: transform components (`translateX/Y/Z`, `rotate*`, `scaleX/Y`, `skewX/Y`) route through the transform accumulator; everything else writes via DOMBatcher. Custom properties (`--name`) supported. Use `template` for non-numeric CSS values: `hsl({value} 80% 65%)`, `hue-rotate({value}deg)`, `circle({value}% at 50% 50%)`. |
totalStagger | float | 0.3 | Fraction of the input progress allocated to staggering element starts. `0.3` = elements start across the first 30% of progress, each animates over the remaining 70%. `0` = all elements start simultaneously (no stagger). `1` = elements fire one-after-another (no overlap, last element animates over a 0-width window). Common range: 0.2 – 0.5. min 0; max 1; step 0.05 |
staggerOrder | enum | "start" | Element ordering for the stagger sequence. `Start → End` (default) cascades from first matched to last. `End → Start` reverses. `Center Out` fans from the middle outward (good for radial / "burst" entrances). `Edges In` converges from the ends toward middle. `Random` shuffles deterministically (seeded) per bind. `Position Y / X` group elements by visual top / left coordinate at bind time so same-row (or same-column) elements share a stagger slot — required for grid layouts where DOM order interleaves columns and you want reveal order to follow what the viewer sees, not source order. options start, end, center, edges, random, positionY, positionX |
Use cases
- Per-character text animation — pair with `splitText` (chars mode) and stack channels: `rotateX` for the rotation wave + `color` (via `template: hsl({value} 80% 65%)`) for a hue cycle + `opacity` for fade. All sharing one stagger window. (See `tube-text` demo.)
- List entrance — `opacity 0 → 1` channel + `translateY 30 → 0` channel + `scaleX 0.96 → 1` channel, one node, cascading fade-and-slide-up.
- Symmetric reveals — `staggerOrder: center` / `edges` with multiple channels (size + opacity + color) for radial / burst reveals.
- Randomized choreography — `staggerOrder: random` with a seed, multi-channel writes for organic / non-deterministic entrances.
Related nodes
Envelope
Use staggerWrite 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-boundary/