Scroller
A scrollytelling container with step-based foreground and background composition. The background content sticks in the viewport while foreground steps scroll over it, with the current step index driving background content changes.
This headless component uses a <div> element with an optional aria-label to create a scrollytelling region with separate background and foreground slots.
Implementation Notes
- Uses
<div>element with classscroller - Background content sticks in viewport while foreground steps scroll over it
- Current step index drives background content changes
- Builds on ScrollerBase primitive internally
- Background uses position: sticky; foreground overlays with pointer-events: none on non-interactive areas
- Steps can contain any content (text, images, charts)
Props
children: slot (required) -- foreground step contentbackground: slot (required) -- sticky background content that changes with stepsoffset: number (default: 0.5) -- viewport offset where step triggersindex: number (bindable, default: 0) -- current active step indexprogress: number (bindable, default: 0) -- overall scroll progress (0-1)label: string (optional) -- accessible label for the scroller region...restProps: Any additional HTML attributes
Usage
<Scroller label="Climate change data story" bind:index>
<div slot="background">
<!-- Changes based on index -->
<img src="chart-{index}.png" alt="Chart showing step {index}" />
</div>
<div class="step">
<p>In 2020, temperatures rose significantly.</p>
</div>
<div class="step">
<p>By 2025, the trend accelerated.</p>
</div>
</Scroller>
<Scroller label="How a vaccine works" bind:index bind:progress>
<div slot="background">
<Animation frame={index} progress={progress} />
</div>
<div class="step">
<p>The vaccine enters the body.</p>
</div>
<div class="step">
<p>It triggers an immune response.</p>
</div>
<div class="step">
<p>Antibodies are produced.</p>
</div>
</Scroller>
Keyboard Interactions
- Standard scroll behavior
- Tab navigates focusable content within steps
ARIA
aria-labelon container whenlabelprop is providedaria-live="polite"on background for screen reader updates when content changes
Composition
- Uses ScrollerBase internally as the scroll-tracking primitive
- Background slot receives the current index and progress for content switching
- Foreground children are passed through to ScrollerBase as steps
When to Use
- Use for data-driven storytelling where visuals change as the reader scrolls
- Use when presenting a narrative with a fixed visual that evolves alongside explanatory text
- Use for interactive articles, data journalism, and educational content
When Not to Use
- Do not use for simple reveal animations -- use a simpler scroll-triggered approach
- Do not use when content does not benefit from scroll-driven narrative
- Do not use for video-driven stories -- use ScrollerVideo instead
Headless
This component provides a <div> element with foreground/background composition and scroll tracking, with zero visual styling. The consumer is responsible for all CSS including background stickiness, foreground overlay positioning, step spacing, and responsive layout.
Styles
The consumer provides all CSS styling. The component renders with a .scroller class for targeting. No default styles are included -- this is a fully headless component.
Testing
- Verify the component renders a
<div>element with classscroller - Verify
aria-labelis applied when label prop is provided - Verify background slot content is rendered
- Verify foreground step content is rendered
- Verify index updates as steps scroll into view
- Verify progress updates as the user scrolls
- Verify
aria-live="polite"is on the background region - Verify pass-through attributes are applied
Advice
- Designers: Design background visuals that transition meaningfully between steps. Ensure foreground text has sufficient contrast against the background at every step. Consider reduced-motion preferences for animated backgrounds.
- Developers: Always provide a descriptive
labelprop for screen reader landmark navigation. Ensure background content updates are communicated viaaria-live. Test with keyboard-only and screen reader navigation.
Related components
scroller-base— see components.tsvscroller-video— see components.tsvhorizontal-scroller— see components.tsvcarousel— a slideshow for cycling through content items
References
- Reuters Graphics Scroller
- Scrollytelling best practices
- ScrollerBase component: ../scroller-base/index.md