Vanilla Breeze

data-stage

Scrollytelling layout pattern: pinned visual on one side, sequential semantic steps on the other. Pure CSS, no scroll listeners.

Pinned visual, sequential steps

The data-stage attribute set provides a layout for staged narrative sections — a pinned visual that stays in view while a column of semantic steps scrolls past. It is pure CSS layout: no scroll listeners, no IntersectionObserver, no JavaScript registry.

Attributes

AttributeRole
data-stageContainer. Sets up a two-column grid on viewports ≥ 60rem; collapses to a single column below that.
data-stage-pinThe visual that stays in view. Pinned with position: sticky on wide viewports; released to static flow on narrow viewports and under reduced motion.
data-stage-stepsAuthoring marker for the column that holds the step sections. Carries no CSS this pass; reserved for future composition.
data-stage-stepOne narrative step. Receives min-block-size: 60vh as a floor so the pinned visual always has scroll room. For scrollytelling, override with min-block-size: 100vh per step so each step occupies roughly one viewport — that's what gives the pin time to read as anchored while the narrative progresses.

Step content reveal

Use the existing data-animate attribute on headings and paragraphs inside each step to fade or slide copy in as it enters the viewport. The same reveals available on any page — fade-up, fade-in, slide-left, scale-up, blur-in — compose directly with the staged layout. There is no separate reveal system to learn.

Responsive behavior

The layout has two states:

  • Wide (≥ 60rem): two columns, pinned visual sticks to the top of the viewport while the step column scrolls.
  • Narrow (< 60rem): single column. The pin releases and content flows naturally. The figure and the steps appear in document order — the narrative reads correctly without any pinning.

This is why data-stage-pin must come before data-stage-steps in the DOM: the document order is the mobile reading order.

Reduced motion

When prefers-reduced-motion: reduce is set, the pin is released regardless of viewport width and copy-reveal animations are disabled by data-animate's own reduced-motion rule. The layout falls back to a flat sequence of figure followed by narrative — readable, complete, and without scroll-coupled movement.

Guidance

  • Use semantic sectioning. The example pairs <figure>, <article>, and <section> intentionally — the staged layout should still convey the right document outline to assistive technology.
  • Don't trap the reader. Each step should make sense on its own. If the next step depends on a state set by motion, the design is over-reaching what the pattern supports.
  • Use scroll-margin-block-start on step headings. Anchor links into a staged section should land below any sticky UI above the stage, not under it.
  • This is layout, not an engine. If you find yourself reaching for active-step state tracking or scroll-progress events, step back and verify whether the layout alone solves the problem first.
  • Top-anchor step content. Avoid display: grid; align-content: center on the step container — vertically centering short copy inside a tall step box creates a long dead gap between the end of one step and the start of the next. Let copy sit at the top of each step and use the remaining height as the pin's scroll runway.