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

@hirasso/restore-scroll

v1.0.0

Published

Vanilla JavaScript scroll restoration for overflowing elements and the window using `history.state` ♻️

Readme

@hirasso/restore-scroll

e2e test status unit test status license

Vanilla JavaScript scroll restoration for overflowing elements and the window using history.state ♻️

Demo

restore-scroll.js.org

Installation

Install and import into your bundle

npm i @hirasso/restore-scroll
import { restoreScroll } from "@hirasso/restore-scroll";

Or import the module directly from a CDN for quick tests:

<script type="module">
  import { restoreScroll } from "https://unpkg.com/@hirasso/restore-scroll@0";
</script>

Usage

/**
 * Track and restore the scroll positions of all overflowing divs,
 * identified by tailwind classes in this case:
 */
document
  .querySelectorAll(".overflow-y-auto,.overflow-x-auto,.overflow-auto")
  .forEach((el) => restoreScroll(el));

💡 If history.scrollRestoration is set to manual, you might want to restore the window scroll position as well:

window.history.scrollRestoration = "manual";
restoreScroll(window);

Arguments

The first argument target accepts either an element or the Window:

export type Target = Element | Window;

The second argument options accepts this:

type Options = {
  debug?: boolean;
  events?: {
    store?: (el: Element, event: CustomEvent<position: ScrollPosition>) => void,
    restore?: (el: Element, event: CustomEvent<position: ScrollPosition>) => void,
  }
}

Options

debug

Type: boolean, default: false. Log debug info to the console

Events

Listening to events can be done in two ways:

Option 1: Attach listeners declaratively

import { restoreScroll } from "@hirasso/restore-scroll";
restoreScroll(el, {
  events: {
    store: (el, event) => console.log("stored", el, event),
    restore: (el, event) => console.log("restored", el, event),
  },
});

Option 2: Attach listeners to the element directly

DOM events are prefixed with restore-scroll::

import { restoreScroll } from "@hirasso/restore-scroll";
const el = document.querySelector("#foo");
el.addEventListener("restore-scroll:restore", (e) => {
  const event = e as CustomEvent<{ position: ScrollPosition }>;
  /** The position is available in event.detail.position */
  console.log(event.detail.position);
});
restoreScroll(el);

event.preventDefault works as expected:

restoreScroll(el, {
  events: {
    restore: (el, event) => {
      if (someCondition()) {
        /** The element won't be restored */
        event.preventDefault();
      }
    },
  },
});

Motivation

There already are other solutions for storing and restoring the scroll position. But all I could find was either archived by their owner, had a dependency (React in most cases) or was using sessionStorage for storing the scroll positions, which is not ideal (with sessionStorage, one URL can only store one scroll state, ever). Hence, this new little package.