1. The Frustrating Reset
While building a search filtering system, I noticed an immediate usability issue. Whenever a user selected a filter, I updated the query parameters using router.push to maintain the application state within the URL.
Instead of the filters simply updating, the entire window scrolled to the Y-axis origin of 0. This behavior is standard for navigation, but for localized state updates, it ruined the focus of the user interaction.
- Injected query parameters using router.push.
- Observed browser window immediately snapping to the top.
- Validated that internal component state remained intact despite the jump.
2. Chasing the Wrong Culprit
Initially, I suspected that my CSS layouts or a global overflow setting were causing the browser to re-render in a way that lost scroll context. I spent time auditing my layout wrapper for fixed heights and flexbox quirks.
It wasn't until I looked at the documentation for the <Link> component that I realized this wasn't a rendering bug at all. It was an intended feature of the navigation API to reset focus and scroll for accessibility.
- Audited CSS for potential overflow or height bugs.
- Checked for accidental focus management libraries interfering with DOM.
- Re-examined standard Next.js navigation behavior.
3. Leveraging Router Options
I knew the <Link> component provided an optional prop to suppress this default behavior. I wondered if the underlying router instance accepted an identical configuration object to handle navigation.
It turns out that the router.push method is significantly more flexible than many realize. It mirrors the configuration object used by Link, allowing us to pass specific control flags directly into the routing engine.
- Identified the scroll property within the navigation API.
- Determined that the router accepts an options object.
- Verified that the default value is true.
4. Disabling the Default Scroll
The fix was surprisingly straightforward. By passing an options object as the second or third argument to push, I could explicitly flip the scroll flag to false. This tells Next.js to modify the URL without touching the current scroll position.
After applying this one-line change, the URL updated silently in the address bar. The page stayed exactly where the user was looking, creating a seamless experience for filter toggling.
- Added the { scroll: false } object to the push call.
- Confirmed the URL updates correctly without scrolling.
- Verified behavior across different browser engines.
FAQ
Does setting scroll to false affect accessibility?
It can. If you are navigating to a completely new page, it is generally better to let the browser reset the scroll to the top for the sake of screen reader users. Only disable it for localized state or query parameter updates.
Can I use this with router.replace?
Yes, both router.push and router.replace support the same options object, allowing you to control scroll behavior identically for both navigation types.