Vanilla JavaScript scroll restoration for overflowing elements and the window using history.state ♻️
Install and import into your bundle
npm i @hirasso/restore-scrollimport { 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>/**
* 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);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,
}
}Type: boolean, default: false. Log debug info to the console
Listening to events can be done in two ways:
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),
},
});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();
}
},
},
});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.