Skip to content

jsonkao/react-scrollama

master
Switch branches/tags
Code

React Scrollama

npm version dependency status

React Scrollama is a lightweight interface for scrollytelling in React. It is adapted from Russel Goldenbeg's Scrollama, and it uses the IntersectionObserver instead of scroll events.

As seen in:


17 interactive visualization
stories
using React Scrollama
for scrollytelling

Comment Tati a imprimé
sa marque à Barbès

by Fabien Casaleggio

The scramble to secure
America’s voting machines

by Beatrice Jin

Sex Diversity Among Grad
Students is Stagnating

by Jason Kao

Demo

Take a look at the live demo, presented at ReactNYC.

Basic step triggers Sticky graphic on the side

Install

React Scrollama can be installed as an npm package:

$ npm install react-scrollama

Note: As of version 2.2.0, the IntersectionObserver polyfill has been removed from the build. You must include it yourself for cross-browser support. Check here to see if you need to include the polyfill.

Usage

A Scrollama component wraps a set of steps. Each Step component must wrap a DOM element.

<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 no-frills 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).

The contributors who made this possible

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

If you need these features ASAP, let us know in issue!