motion-scene

Scroll-driven animation timeline. Pin a stage while scroll progress drives children through keyframes. It's purely declarative, using data attributes.

Live showcase Declare · Sequence · Compose

How 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-startdata-end (0–1 progress values).

Preview

Scroll inside the box to drive the animation.

STEP_01
STEP_02
STEP_03

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

pin defaults to true and, like any HTML boolean attribute, cannot be switched off from markup: both omitting it and writing pin="false" leave it true. Set the property to get scrubbed children without a sticky stage.

Properties

Attribute Property Type Default Description
height height string '200vh' Height of the scroll container: controls how much scroll the scene consumes.
pin pin boolean true The inner stage sticks to the viewport while scrolling. Cannot be switched off from markup; set el.pin = false
container container string '' CSS selector for a custom scroll container. Defaults to document scroll when empty.

Child data attributes

Property Type Default Description
data-from JSON Starting keyframe, e.g. {"opacity":0,"y":"-20px"}. Supports x, y, scale, rotate, and any CSS property.
data-to JSON Ending keyframe, same shape as data-from.
data-start number 0 Scene progress (0–1) at which this child's animation begins.
data-end number 1 Scene progress (0–1) at which this child's animation ends.

JavaScript API

Control the scene programmatically with play(), pause(), finish(), and cancel(). Pause unbinds the scroll listener so the card freezes mid-scrub. Finish snaps to the end keyframe. Cancel resets to the start. Scroll the box while running to drive the card.

Scene API demo
playState:

Accessibility

Respects prefers-reduced-motion: when enabled, all scroll-driven animations are disabled and children render at their end state immediately.