npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zeitonline/scrolleo

v1.0.3

Published

Lightweight scrollytelling library using IntersectionObserver

Readme

Scrolleo

A modern & lightweight Vanilla JS library for scrollytelling experiences

npm version License: MIT

No dependencies, no framework, pure ESM.

About

Scrolleo is a modernization of scrollama with:

  • Performance improvements
  • Improved TypeScript definitions
  • A modern ESM-only build

Why?

Scrollytelling can be complicated to implement and difficult to make performant. The goal of this library is to provide a simple interface for creating scroll-driven interactives. Scrolleo is focused on performance by using IntersectionObserver to handle element position detection.

Examples

Check out the demo gallery to see Scrolleo in action:

Installation

npm install @zeitonline/scrolleo

And then import it:

import scrolleo from '@zeitonline/scrolleo';

How to use

Basic

Create step elements in your HTML:

<section id="scrolly">
	<article>
		<div class="step">
			<p>Step 1</p>
		</div>
		<div class="step">
			<p>Step 2</p>
		</div>
		<div class="step">
			<p>Step 3</p>
		</div>
	</article>
</section>

Then initialize Scrolleo and set up your callbacks:

import scrolleo from '@zeitonline/scrolleo';

// Create a scrolleo instance
const scroller = scrolleo();

// Setup with options and attach callbacks
scroller
	.setup({
		step: '#scrolly article .step',
		offset: 0.5, // Trigger when step is 50% from top of viewport
		debug: false, // Set to true to see visual debugging
	})
	.onStepEnter((response) => {
		// Called when a step enters the offset threshold
		const { element, index, direction } = response;
		element.classList.add('is-active');
		console.log(`Step ${index} entered from ${direction}`);
	})
	.onStepExit((response) => {
		// Called when a step exits the offset threshold
		const { element, index, direction } = response;
		element.classList.remove('is-active');
		console.log(`Step ${index} exited to ${direction}`);
	});

The response object contains:

  • element: The DOM element that triggered the callback
  • index: The zero-based index of the step
  • direction: Either 'up' or 'down' indicating scroll direction

API

scrolleo.setup([options])

options:

| Option | Type | Description | Default | | --------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | | step | string or HTMLElement[] | required Selector (or array of elements) for the step elements that will trigger changes. | | | offset | number (0 - 1, or string with "px") | How far from the top of the viewport to trigger a step. | 0.5 | | progress | boolean | Whether to fire incremental step progress updates or not. | false | | threshold | number (1 or higher) | The granularity of the progress interval in pixels (smaller = more granular). | 4 | | once | boolean | Only trigger the step to enter once then remove listener. | false | | debug | boolean | Whether to show visual debugging tools or not. | false | | parent | HTMLElement[] | Parent element for step selector (use if you steps are in shadow DOM). | undefined | | container | HTMLElement | Parent element for the scroll story (use if scrollama is nested in a HTML element with overflow set to scroll or auto) | undefined | | root | HTMLElement | The element that is used as the viewport for checking visibility of the target. Must be the ancestor of the target. Defaults to the browser viewport if not specified or if null. See more details about usage of root on MDN. | undefined |

scrolleo.onStepEnter(callback)

Callback that fires when the top or bottom edge of a step element enters the offset threshold.

The argument of the callback is an object: { element: DOMElement, index: number, direction: string }

element: The step element that triggered

index: The index of the step of all steps

direction: 'up' or 'down'

scrolleo.onStepExit(callback)

Callback that fires when the top or bottom edge of a step element exits the offset threshold.

The argument of the callback is an object: { element: DOMElement, index: number, direction: string }

element: The step element that triggered

index: The index of the step of all steps

direction: 'up' or 'down'

scrolleo.onStepProgress(callback)

Callback that fires the progress (0 - 1) a step has made through the threshold.

The argument of the callback is an object: { element: DOMElement, index: number, progress: number }

element: The step element that triggered

index: The index of the step of all steps

progress: The percent of completion of the step (0 - 1)

direction: 'up' or 'down'

scrolleo.offset([number or string])

Get or set the offset percentage. Value must be between 0-1 (where 0 = top of viewport, 1 = bottom), or a string that includes "px" (e.g., "200px"). If set, returns the scrolleo instance.

scrolleo.resize()

This is no longer necessary with the addition of a built-in resize observer. Tell scrolleo to get latest dimensions the browser/DOM. It is best practice to throttle resize in your code, update the DOM elements, then call this function at the end.

scrolleo.enable()

Tell scrolleo to resume observing for trigger changes. Only necessary to call if you have previously disabled.

scrolleo.disable()

Tell scrolleo to stop observing for trigger changes.

scrolleo.destroy()

Removes all observers and callback functions.

custom offset

To override the offset passed in the options, set a custom offset for an individual element using data attributes. For example: <div class="step" data-offset="0.25"> or data-offset="100px".

Alternatives

Credits

This project is a modernization and rebrand of scrollama by Russell Samora.

Original scrollama is licensed under the MIT License. This version maintains the same license and includes the original copyright notice. Scrolleo is maintained by DIE ZEIT / ZeitOnline.

License

MIT License - see LICENSE file for details.