motion-scene
Scroll-driven animation timeline. Pin a stage while scroll progress drives children through keyframes — purely declarative via data attributes.
Live showcase → Declare · Sequence · ComposeHow it works
Wrap a scene in a tall container. The inner stage sticks while the user scrolls. Children with data-from/data-to are scrubbed from their start keyframe to their end keyframe as scroll advances through data-start–data-end (0–1 progress values).
Preview
Scroll inside the box to drive the animation.
Import
CSS variable
The scene exposes --progress (0–1) so you can drive your own CSS effects off scroll position.
Custom scroll container
By default the scene tracks document scroll. Pass a CSS selector via container to use an overflow element instead.
Without pinning
Set the pin attribute to false (omit it) if you want scrubbed children but no sticky stage.
Properties
| Attribute | Property | Type | Default | Description |
|---|---|---|---|---|
| | | string | '200vh' | Height of the scroll container — controls how much scroll the scene consumes. |
| | | boolean | true | When present, the inner stage sticks to the viewport while scrolling. Omit to disable. |
| | | string | '' | CSS selector for a custom scroll container. Defaults to document scroll when empty. |
Child data attributes
| Property | Type | Default | Description |
|---|---|---|---|
| | JSON | — | Starting keyframe — e.g. {"opacity":0,"y":"-20px"}. Supports x, y, scale, rotate, and any CSS property. |
| | JSON | — | Ending keyframe — same shape as data-from. |
| | number | 0 | Scene progress (0–1) at which this child's animation begins. |
| | number | 1 | Scene progress (0–1) at which this child's animation ends. |
Accessibility
Respects prefers-reduced-motion: when enabled, all scroll-driven animations are disabled and children render at their end state immediately.