Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Scrollytelling layout pattern: pinned visual on one side, sequential semantic steps on the other. Pure CSS, no scroll listeners.
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.
<section data-stage> <figure data-stage-pin> <img src="/images/scene.jpg" alt="" /> <figcaption>Supporting visual</figcaption> </figure> <article data-stage-steps> <section data-stage-step> <h2 data-animate="fade-up">Introduce the subject</h2> <p data-animate="fade-up">Opening narrative paragraph.</p> </section> <section data-stage-step> <h2 data-animate="fade-up">Reveal the tension</h2> <p data-animate="fade-up">Second step advances the story.</p> </section> </article></section>
| Attribute | Role |
|---|---|
data-stage | Container. Sets up a two-column grid on viewports ≥ 60rem; collapses to a single column below that. |
data-stage-pin | The 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-steps | Authoring marker for the column that holds the step sections. Carries no CSS this pass; reserved for future composition. |
data-stage-step | One 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. |
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.
<section data-stage-step> <h2 data-animate="fade-up">Step heading</h2> <p data-animate="fade-up">Body copy fades in as the step enters view.</p></section>
The layout has two states:
This is why data-stage-pin must come before data-stage-steps in the DOM: the document order is the mobile reading order.
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.
<figure>, <article>, and <section> intentionally — the staged layout should still convey the right document outline to assistive technology.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.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.