Open LeakedDave opened 3 months ago
Adding scroll restoration to a particular element is something I am currently using. Glad to see it added here.
Once criticism I received for the storing x,y position approach is that the user could change the size of the browser. Any thoughts? I stuck with it x,y position as it seems like a bit of an edge case, extra complexity of determining which element should scroll into view, and the possibility that elements re-flowing at different browser sizes might lead to imperfect results anyhow.
You could do a percentage based scroll maybe? Like instead of storing scrollX and scrollY directly, store it as a percentage of the width and height of the window or element that has overflow. Then on restore, convert that percentage to a position.
Also for iOS it's best to do this
window.history.scrollRestoration = iOS() ? 'auto' : 'manual'
export const iOS = () => {
return navigator.userAgent.match(/(iPad|iPhone|iPod)/g)
// iPad on iOS 13 detection
|| (navigator.userAgent.includes("Mac") && navigator.maxTouchPoints > 1)
}
That's an interesting idea. Might at least get you closer than x,y in situations where page elements re-flow.
Scrolling and navigating around a handful of random sites now and I haven't found any where content re-flows and I'm returned to the same element after a browser resize.
I updated the scripts a bit. I'm using window.history.state.key to track positions, so it supports going to the same page throughout history and always restoring the correct scroll position. This also fixes iOS Snapshots, since I don't set window.scrollRestoration to manual.
I also allow you to set a selector for an element to restore scroll to, for my website I have an "overflow-y-auto" child element that I need scrollRestoration for, so window won't do the trick. Here is my updated, versatile script for 2024 lol.
I also added an option to add a delay if you need to, and I moved router into the options, it will default to useRouter if you don't provide one.
useScrollRestoration.js
Default setup: useScrollRestoration()
Scroll child element
<main>
with overflow: useScrollRestoration(router, { selector: "main" })Delay Example: useScrollRestoration(router, { delay: 100 })