-
Notifications
You must be signed in to change notification settings - Fork 27.1k
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
Scroll restoration happens too early before the page gets rendered after hitting browser back button #3303
Comments
This seems to happen because next's router (and This is an interesting article about how scroll restoration works on each browser. Basically you can disable it and manage the scroll on your own: history.scrollRestoration = 'manual' |
Thanks for you explanation.
Using a plain `<a />` tag would cause a full page reload, which is not what I expected. I expect the back button would either not trigger the `getInitialProps` method or don’t restore scroll until the `getInitialProps` is finished
… On 28 Dec 2017, at 12:10, Pablo Varela ***@***.***> wrote:
This seems to happen because next's router (and <Link />) uses window.history.pushState and then window.history.back restores the scroll. This doesn't happen with common <a /> because it doesn't use pushState.
This is an interesting article <https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration> about how scroll restoration works on each browser. Basically you can disable it and manage the scroll on your own:
history.scrollRestoration = 'manual'
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#3303 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AAncD7Vrn7rZJW5NYdokbPsXWn7O4N5Eks5tExSmgaJpZM4QiFwt>.
|
Yeah, I understand. I'm not sure what the solution would be from within next. |
@liweinan0423 I'm not sure but this could be a workaround |
We've come across this too and it feels like something next should be doing internally. Otherwise everyone needs to write their own code to store scrollpositions and then scroll on completion of getInitialProps. |
we're having a related issue where, upon clicking a link from a scrolled-down position (say, result 20 in a list) the new page shows up halfway down so the user needs to scroll up to see the item itself. |
We're also running into this issue and it makes the user experience very frustrating to use. @arunoda Any thoughts or way to fix this? |
I was having this same issue as @mgiraldo awhile back and I originally was just using router.push(), but as soon as I switched to using the tag, my problem resolved itself with out needing to implement a hack like scroll-to-top in component did mount or something ghetto like that. Curious if you are using a Link tag at all? |
it is a regular but we ended up using feels very hacky, though... and we have the Back button issue mentioned in the issue in other parts of the site. you can see the problem in action here: https://dp.la/exhibitions (scroll down and click)... the patch will be up tomorrow |
you can see the patched version here: https://beta-staging.dp.la/exhibitions |
@mgiraldo I see a slight flash when using the back button. We're running into the same issue. |
@mgiraldo In another part of my site I forgot I did this:
which works when navigating TO a page, but like you said when you hit the back button, its at the top of the window because I think the window recorded that in its history.... |
@spencersmb What do you mean switch to using the tag? What tag is that? |
We've a similar issues reported here: https://spectrum.chat/thread/3d65b436-b085-4eef-ad84-0941c473e09d Next.js doesn't hijack scrolling. But this is a real issue. Here's what's happening. When you go back, browser tries to go to the previous scroll position for better UX. But in the ^^ case, the data is not loaded yet. But the data will be there in a bit with the latency of So, in order fix this you can do a few things:
We've no plan to manage scrolling inside Next.js yet. But you can do it in the userland and publish a new Link component like |
I mean every time a javascript library gets popular and people start using it in production ... some majors issues show up and the official response is: "Fix it yourself." 😢 I fail to understand how does @mgiraldo Posted a link to a patched version of his website.
There are two major issues:
I believe it would be nice to at least consider fixing this issue in the future. Other than that thanks for all the hard work that you put in nextjs. It might take a little longer but we are getting closer to stable libraries in javascript community. |
@developer239 We have the exact same issue with our Next.js app as documented here: https://spectrum.chat/thread/3d65b436-b085-4eef-ad84-0941c473e09d It completely kills the user experience. Basically, the current page scrolls to the bottom of the page because it's trying to restore scroll position before the previous page is rendered. @arunoda Could you explain why the Next team isn't considering an official fix to this issue? It seems like it's a breaking bug that completely ruins the user experience. |
if i understand correctly the back button/scroll position functionality is a native browser behavior that assumes a standard page refresh (user goes from url x to url y via a standard http request). what client-side javascript-based frameworks do is implement a page transition without making use of the native browser behavior (via what i think the nextjs team is saying is the effort of implementing a cross-browser solution to this problem is beyond the scope they are willing to take on. |
I think if a next.js team provides its own routing management they should care about similar critical issues as well. For example react-router doesn't have this issue and they don't think that is should be implemented by another developer themselves. |
Hi to all! I think i solve this issue by following the advice of @pablopunk Strange thing, by using and removing it, it seems that it also fix the issue in a build that is deployed with now. Maybe is only a browser issue? |
I came across mentioned issue while building my portfolio site and I think this is really a big breaking thing in user experience overall. |
My solution for restoring scroll position when the browser back button clicked: _app.js
|
@hardwit well done!
|
Where does Router come from? |
This worked for me: _app.js
|
I'm my project, sometimes I can't even scroll down after changing page in development... if it was a production issue I'd switch framework. |
Hi ! It seems to still not work on nextjs.org with Chrome iOS when I click on footer links. Tested with Chrome IOS (v.96.0.4664.101) on 15.1 and 14.7. Image.from.iOS.MP4 |
Welp, I just ran into this issue 2 days before I'm scheduled to ship my project... None of the solutions work. Nextjs has been awesome, but this bug really sucks. Any chance this has been looked at recently? |
@dejesus2010 Trying to get this solved since last month but still didn't get any solution. |
I'm having the same issue. I've added a setTimeout to delay the scroll, but this is obviously not a sustainable solution. |
next: 12.2.2 module.exports = {
experimental: {
scrollRestoration: true
}
} this flag triggers const router = useRouter();
const scrollCache = useRef<Record<string, [number, number]>>({});
const activeRestorePath = useRef<string>();
useEffect(() => {
if (history.scrollRestoration !== "manual") {
history.scrollRestoration = "manual";
}
const getCurrentPath = () => location.pathname + location.search;
router.beforePopState(() => {
activeRestorePath.current = getCurrentPath();
return true;
});
const onComplete = () => {
const scrollPath = activeRestorePath.current;
if (!scrollPath || !(scrollPath in scrollCache.current)) {
return;
}
activeRestorePath.current = undefined;
const [scrollX, scrollY] = scrollCache.current[scrollPath];
const delays = [0, 10, 20, 40, 80, 100, 100, 100, 100];
const checkAndScroll = () => {
if (scrollPath !== getCurrentPath()) {
return;
}
const docEl = document.documentElement;
const maxScrollY = docEl.scrollHeight - docEl.clientHeight;
const maxScrollX = docEl.scrollWidth - docEl.clientWidth;
if (maxScrollX >= scrollX && maxScrollY >= scrollY) {
window.scrollTo(scrollX, scrollY);
} else {
const delay = delays.shift();
if (delay) {
setTimeout(checkAndScroll, delay);
}
}
};
setTimeout(checkAndScroll, delays.shift());
};
const onScroll = () => {
scrollCache.current[getCurrentPath()] = [window.scrollX, window.scrollY];
};
router.events.on("routeChangeComplete", onComplete);
window.addEventListener("scroll", onScroll);
return () => {
router.events.off("routeChangeComplete", onComplete);
window.removeEventListener("scroll", onScroll);
};
}, []); hope it helps |
This does not work for me bro! |
@jsvelte I updated code. after using it for a few days I noticed it doesn't work on IOS safari. I noticed calling |
I'm kinda at my wits end with this one. I'm not sure if I'm just having a configuration issue or what's going on, but surely the intended behavior is not to maintain scroll position when loading a new page? Currently clicking any Is the intended behavior out of the box for From what I've been reading the answer seems like this is not the intended default behavior (which makes sense to me). So my question then becomes, is this a bug? Or is this some configuration issue on my end? If it is a configuration issue, where can I look to either confirm/ fix that issue. |
Absolutely mental that this hasn’t been solved in four years! But there you go... |
Just noting that this also seems to be an issue with Next's own |
I settled on this version of the scroll next.config.js change scrollRestoration to false
_app.tsx add to App function
Link needs to disable scrolling
|
It seems that the official documentation has not handled scrolling restoration well. Screen.Recording.2023-06-21.at.14.06.00.movRPReplay_Final1687327053.mp4 |
For anyone working with or without Framer – hopefully this helps as an easy solution. If you aren’t using Framer, you can follow Jakob Chill’s post here: https://jak-ch-ll.medium.com/next-js-preserve-scroll-history-334cf699802a
|
It's an infinite scroller, getting scroll restoration right with those is not trivial |
Good news: This issue has been solved in App Router, we've kept it in mind from the start when building the new router. For App Router we've changed this, the router is built around a client-side cache that is reused when navigating back/forward. In addition to that we've made changes in React to support React Transitions being synchronous when triggered in the |
This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
After transiting from one page to another page via next
<Link />
, if user clicks the back button and the previous page hasgetInitialProps
method that takes some time to finish, the scroll position of the previous will be restored before the previous pages gets rendered.Demo
source code can be found here
After clicking back button, the "go back" text should still be visible (not scroll down to previous position) until the previous page gets rendered
The text was updated successfully, but these errors were encountered: