-
Notifications
You must be signed in to change notification settings - Fork 26.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Opt out of scroll restoration when using browser back buttons #20951
Comments
I’ve found a pretty good solution in the following: router.beforePopState((state) => {
state.options.scroll = false;
return true;
}); |
Next.js should not reset the scroll position to 0,0 on back or forwards navigation. Could you please share a reproducible demo for this behavior? We have tests covering this in Chrome. |
Sure, @Timer: I created a repository showing the behavior by the following steps:
For debugging purposes, I also went into the local if (input.scroll) {
+ console.log('Scrolling to', input.scroll.x, input.scroll.y);
window.scrollTo(input.scroll.x,input.scroll.y);
} Now, I can navigate from page A to page B, and observe that when I press the browser “back” button, a message is printed to the console indicating that Next.js is scrolling the page to the top. Here’s a video: 20951-repro-video.movYou can see that the console message is printed, indicating that Next.js initiates a scroll to (0, 0). |
The behavior you just displayed in video was correct, though. The scroll should be restored to its location on Page A (the top). I agree the console log is weird, but what happens if you scroll Page A before going to B, and then back to A? I can't reproduce this issue in a normal app (console.log aside, the scroll doesn't appear to be taking affect even though it's called). |
Here's the alternate test case you described. I:
As you can see, the page still jumps to the top of the page, and the scrollTo code in client/index.jsx still executes with (0, 0). Here's a video showing that: Screen.Recording.2021-01-12.at.11.37.48.AM.mp4I'm not sure that even the first behavior I showed was correct, though — given that I set |
Oh, this seems to be specific to I can fix this. |
We are having a problem with this behavior too. @Timer, do you have any planned date when this issue is expected to be fixed? It would help us a lot. |
This issue blocking me too. There is no way to disable this unnecessary behavior for now. |
I've tried this but it didn't work. |
Hi @Timer Can we use
as a workaround while this issue is not officially solved ? |
This works for me! |
This worked well for me as well! |
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as off-topic.
This comment was marked as off-topic.
Worked fine for me:
|
There is an issue with all of these solutions that I am not sure has been noticed. On iOS WebKit there is a check that a snapshot should only be shown for a back or forward action if Here is an example on the Target website that uses Next: target.movNotice if both screens are scrolled to top the snapshot is shown, but Target has some form of scroll restoration it seems so the manual setting screws up the page. The only solution I found so far for my own project is to check for webkit and not set
|
@nhannah Thanks for noticing that iOS safari issue! Hopefully the Next authors will take it into account if they ever address this glaring problem. Gatsby has excellent built-in scroll restoration so we've been quite surprised to have to patch it. Users have been posting about it since 2017 🤷 Your sniff is a little too broad though, gets picked up by Firefox. I used, // Manual doesn't work well on iOS Safari https://github.com/vercel/next.js/issues/20951#issuecomment-1231966865
const ua = window.navigator.userAgent.toLowerCase();
const isMobileSafari = /safari/.test(ua) && /iphone|ipod|ipad/.test(ua);
window.history.scrollRestoration = isMobileSafari ? 'auto' : 'manual'; I updated the hook to include that and some other niceties at the main gist here: https://gist.github.com/claus/992a5596d6532ac91b24abe24e10ae81?permalink_comment_id=4301903#gistcomment-4301903 |
@tomiviljanen CC @ijjk hi I tried the experimental scroll restoration and it worked pretty well. It has a few outstanding issues though:
I know there are a number of other open issues out there on all of this but just wanted to list these out clearly. Seems that the experimental feature isn't super close to production-ready yet. When testing the feature, I'd suggest using a full web page with a good amount of content on it, since it seems like React's hydration lifecycle interacts with this and there are little race conditions happening. (I don't mean this as a dig at all, but you might also peek at how Gatsby does theirs as it is quite solid.) |
Working nicely for me |
For me it was just the window history scroll restoration window.history.scrollRestoration = "manual"; Here is a good article I found https://developer.chrome.com/blog/history-api-scroll-restoration/ |
Dropping a note that |
Just add this in nextjsconfig module.exports = { |
I am using
|
Hi everyone! I will be closing this issue since this is resolved with Feel free to submit a new bug report if you are still experiencing scroll issues! |
@samcx This issue is explicitly about controlling the behavior when not using The original issue notes the existence of the This issue is unresolved and should be reopened. |
@controversial Thank you for the clarification—my apologies for not reading the issue correctly. It might be possible for us to have this experimental API (which only works with Pages Router)
to add |
@samcx This works in Next 13 dev mode, but in production in standalone mode it doesn't work. Any ideas? |
@rhd-developers Are you using Pages Router? If yes, can you provide us a simple |
Can we extend the OP question to simply ask how to Opt out completely of any native NextJS scroll management at all? We know scrollRestoration and scrollBehavior are for different purposes but would like to propose that they both fall under scrollManagement with relation to routing. We are wanting to completely disable native scroll management so that we have complete control over "when" scrollRestoring happens in time. This is because we are implementing complex Page Transition animations that:
Since these animations are timed, we need to control when the restore, or any scrollTo 's happen. These means two things for us:
ISSUE #1:
Nothing seems to work, even though we can see many places in the core code that reference this env var ISSUE #2: We have things working by disabling all Would LOVE some incite here or guidance if anyone has any. |
@iDVB I assume you're using App Router instead of Pages Router? That would explain why that configuration doesn't work (issue #1).
You could also just create a custom Would a config to opt out of any |
We ended up expanding on @claus 's ScrollRestoration above. This works with the latest version of NextJS and Page Router, although it may also work with App Router, but we've not tested. The primary purpose of this for us was to haven the ability to control "when" scroll was restored for certain routes where we have custom page transitions that use gsap animation lib. Added support for:
https://gist.github.com/iDVB/4f6ba81d4cdf37dd16fefdfca0fd5777 |
Describe the feature you'd like to request
There is a clear way to opt out of Next.js scroll restoration when using
Link
orrouter.push
: just pass{ scroll: false }
. However, I haven't found a clear way to opt out of scroll restoration when using the browser back/forward buttons.I spent a little while reading the source of the
popState
handler, and it seems like the router will always jump either to the scroll position in sessionStorage or to the top of the page.Describe the solution you'd like
Ideally, there would be some kind of router configuration option by which an app could opt out of the router messing with scroll position completely.
Describe alternatives you've considered
I've considered trying to mess with the scroll value stored in
sessionStorage
duringonPopState
, but this seems like a really convoluted workaround that might not hold up in future Next.js releases.The text was updated successfully, but these errors were encountered: