React Scrollama is a simple and silky library for scrollytelling. It relies on IntersectionObserver and sticky positioning over scroll listeners. It is originally adapted from Russell Samora's Scrollama.
A few examples of ambitious interactive stories that were built with React Scrollama…
Demo
A live demo lives here.
| Basic step triggers | Sticky graphic on the side |
|---|---|
![]() |
![]() |
Install
React Scrollama can be installed as an npm package:
$ npm install react-scrollama
Usage
A Scrollama component wraps a set of steps. Each Step component must wrap a DOM element (i.e. not just text).
<Scrollama onStepEnter={callback} offset={0.5}> <Step data={1}> <div>...</div> </Step> <Step data={2}> <div>...</div> </Step> </Scrollama>
<Scrollama> provides an interface for listening in on scroll triggers like entering or exiting a step. (Here's a full list of available props.)
A basic example:
import React, { useState } from 'react'; import { Scrollama, Step } from 'react-scrollama'; const ScrollamaDemo = () => { const [currentStepIndex, setCurrentStepIndex] = useState(null); // This callback fires when a Step hits the offset threshold. It receives the // data prop of the step, which in this demo stores the index of the step. const onStepEnter = ({ data }) => { setCurrentStepIndex(data); }; return ( <div style={{ margin: '50vh 0', border: '2px dashed skyblue' }}> <div style={{ position: 'sticky', top: 0, border: '1px solid orchid' }}> I'm sticky. The current triggered step index is: {currentStepIndex} </div> <Scrollama offset={0.5} onStepEnter={onStepEnter} debug> {[1, 2, 3, 4].map((_, stepIndex) => ( <Step data={stepIndex} key={stepIndex}> <div style={{ margin: '50vh 0', border: '1px solid gray', opacity: currentStepIndex === stepIndex ? 1 : 0.2, }} > I'm a Scrollama Step of index {stepIndex} </div> </Step> ))} </Scrollama> </div> ); }; export default ScrollamaDemo;
API
React Scrollama components do not render into the DOM. They are meant to set up Intersection Observers on the elements inside the <Step> components. In the code above, only the <div> elements would show up in the DOM.
Scrollama
These are the props you can set on the Scrollama component itself:
| Prop | Type | Default | Description |
|---|---|---|---|
| offset | number (from 0 to 1) or pixel value (e.g. "300px") |
0.3 | How far from the top of the viewport to trigger a step (as a proportion of view height) |
| threshold | number (greater than 1) |
4 | Granularity of the progress interval in pixels (smaller = more granular) |
| onStepEnter | function |
Callback that fires when the top or bottom edge of a step enters the offset threshold. | |
| onStepExit | function |
Callback that fires when the top or bottom edge of a step exits the offset threshold. | |
| onStepProgress | function |
Callback that fires the progress a step has made through the threshold. | |
| debug | boolean |
false | Whether to show visual debugging tools. |
The onStepEnter and onStepExit callbacks receive one argument, an object, with the following properties:
{ element, // The DOM node of the step that was triggered data, // The data supplied to the step direction, // 'up' or 'down' entry, // the original `IntersectionObserver` entry }
The onStepProgress callback receives one argument, an object, with the following properties:
{ element, // The DOM node of the step that was triggered data, // The data supplied to the step progress, // The percent of completion of the step (0 to 1) direction, // 'up' or 'down' entry, // the original `IntersectionObserver` entry }
To create a fixed graphic with text scrolling beside/over it, use position: sticky;. How to use position sticky.
Step
A Step element can contain one child, which must be a DOM element. To use a React component as the child node, it must be wrapped with a DOM element like <div>.
These are the props you can set on the Step component:
| Prop | Type | Default | Description |
|---|---|---|---|
| data | any | Data to be given to <Scrollama> callbacks when step triggered. |
You will also probably want to set a key prop on each Step if you're transforming an array of data into a list of Step elements (see Lists and Keys).
Thank you to everyone who made this possible!
- maerzhase
- NicholasLYang
- jonesbp
- kennethormandy
- cedricdelpoux
- davidnmora
- jefffriesen
- paolocorti
- elbertwang3
- michaelgrotton
- jjrchrds
- goleary
- danieleguido
- Lane
- jkjustjoshing
- tuckergordon
- fschwander
- thisispaul
Features roadmap
- Currently, there is no way to throttle/customize React Scrollama's resize listener 😢. We're working on this in #44.
- Fire previous step triggers if they were jumped
Lmk if you need these features ASAP.

