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 🙏

© 2024 – Pkg Stats / Ryan Hefner

scroll-scene-element

v0.1.1

Published

A tiny custom element for all your scrollytelling needs.

Downloads

19

Readme

<scroll-scene> element

A tiny custom element for all your scrollytelling needs! The successor to @newswire/scroller.

Key features

  • 🐜 ~700 bytes brotli'ed, ~800 bytes gzip'ed
  • 👀 Uses a highly-performant Intersection Observer to monitor scrolling changes
  • 📚 Smartly uses scroll events to calculate scroll progress only when needed
  • 🌻 Each <scroll-scene> element may have its own offset and opt-in to progress events
  • 🙅🏽‍ No dependencies

Examples

Installation

npm install scroll-scene-element
// or
yarn add scroll-scene-element
// or
pnpm add scroll-scene-element

Usage

In your HTML add <scroll-scene> container elements around every "scene" you want to track the progression of in your interactive. Feel free to use these elements as the containers of your graphics or other dynamic content and style them as needed - all progression and scroll depth changes will be tracked on the tag and its contents.

<div class="scrollytelling-container">
	<scroll-scene>
		<h2>Scene 1</h2>
		<p>This is the first scene.</p>
	</scroll-scene>
	<scroll-scene>
		<h2>Scene 2</h2>
		<p>This is the first scene.</p>
	</scroll-scene>
	<scroll-scene>
		<h2>Scene 3</h2>
		<p>This is the first scene.</p>
	</scroll-scene>
</div>

Then import the script as an ES module in your bundle or load via a script tag to upgrade the <scroll-scene> elements:

import 'scroll-scene-element';

or

<script src="https://unpkg.com/scroll-scene-element/dist/scroll-scene-element.js" type="module"></script>

If you have experience with Scrollama or @newswire/scroller it may be surprising that there's no "init" step. Thanks to custom elements the initalization happens automatically just by using <scroll-scene>.

Events with <scroll-scene> work just like others in JavaScript giving you the same amount of flexibility. (And familiarity!) scroll-scene-enter, scroll-scene-exit and scroll-scene-progress all bubble up to document. If you know there will only be a single set of <scroll-scene> elements on a page you may listen on document directly:

document.addEventListener('scroll-scene-enter', (event) => {
	// "event" is a CustomEvent, giving it has a `detail` property
	const detail = event.detail;

	// the triggering element
	const element = event.element;

	// just like in standard DOM events, "target" is also the triggering element
	const target = event.target;

	// the bounds of the triggering element
	const bounds = detail.bounds;

	// whether the page was scrolling up or down when the event was triggered
	const isScrollingDown = detail.isScrollingDown;

	// the offset used for this element
	const offset = detail.offset;
});

But what if you have more than one set of <scroll-scene> elements on a page? You might instead attach your listener to a parent element of each set of <scroll-scene> elements:

const container = document.querySelector('.scrollytelling-container');

container.addEventListener('scroll-scene-enter', (event) => {
	// no need to allow it to bubble up to `document`
	event.stopPropagation();

	// "event" is a CustomEvent, giving it has a `detail` property
	const detail = event.detail;

	// ...
});

And finally - you may attach your listener to each <scroll-scene> element individually:

const scenes = document.querySelectorAll('scroll-scene');

scenes.forEach((scene) => {
	scene.addEventListener('scroll-scene-enter', (event) => {
		// no need to allow it to bubble up to `document`
		event.stopPropagation();

		// "event" is a CustomEvent, giving it has a `detail` property
		const detail = event.detail;

		// ...
	});
});

Maybe you only need to know the first time a scene enters (or exits) the viewport? You can use the native once option with addEventListener:

const scene = document.querySelector('scroll-scene');

scene.addEventListener(
	'scroll-scene-enter',
	() => {
		console.log('Entered!');
	},
	{ once: true },
);

scene.addEventListener(
	'scroll-scene-exit',
	() => {
		console.log('Exited!');
	},
	{ once: true },
);

If a <scroll-scene> element opts-in to progress tracking, it will emit a scroll-scene-progress event when the progress changes once it enters and stop emitting the event once it exits. This event will bubble up to document:

<scroll-scene progress>
	<h2>Scene 1</h2>
	<p>This is the first scene.</p>
</scroll-scene>
const scene = document.querySelector('scroll-scene');

scene.addEventListener('scroll-scene-progress', (event) => {
	// "event" is a CustomEvent, giving it has a `detail` property
	const detail = event.detail;

	// the triggering element
	const element = event.element;

	// `event.target` is also the triggering element, just like in standard DOM events
	const target = event.target;

	// the bounds of the triggering element
	const bounds = detail.bounds;

	// the offset used for this element
	const offset = detail.offset;

	// the progress of the element from 0 to 1
	const progress = detail.progress;
});

Attributes

A <scroll-scene> element has two optional attributes:

  • offset: a number between 0 and 1 that determines how far from the top of the viewport the element must be before a scroll-scene-enter or scroll-scene-exit event is triggered. Defaults to 0.5.
  • progress: a boolean that determines whether the scroll-scene-progress event is triggered. Defaults to false.

These can be set on the <scroll-scene> element as an attribute or be passed in as a property.

<scroll-scene offset="0.75"></scroll-scene>
<scroll-scene progress></scroll-scene>
const scene = document.querySelector('scroll-scene');

// as properties
scene.offset = 0.75;
scene.progress = true;

// as attributes
scene.setAttribute('offset', '0.75');
scene.setAttribute('progress', '');

Events

Viewport events

scroll-scene-enter is emit when an element enters the viewport. scroll-scene-exit is emit when an element exits the viewport. Both events bubble up to document. They both have a detail property that contains the following:

  • bounds: the bounds (DOMRectReadOnly) of the triggering element as made available within the IntersectionObserver callback
  • element: the triggering element
  • isScrollingDown: whether the page was scrolling up or down when the event was triggered
  • offset: the offset used for this element

Progress event

scroll-scene-progress is emitted when the progress of an element changes. It bubbles up to document and has a detail property that contains the following:

  • bounds: the bounds (DOMRect) of the triggering element
  • element: the triggering element
  • offset: the offset used for this element
  • progress: the progress of the element from 0 to 1

License

MIT