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
Next 12.3.1 breaks smooth-scrolling, change made in 12.3.1-canary.4, woks in 12.3.1-canary.3 and before #40719
Comments
@timneutkens @cramforce It seems that several people confirm this problem. Have you taken a look at this problem yet? |
any update for this? |
@gurkerl83 I'm trying to understand what the problem is with the change that was landed, it implements exactly the behavior that is intended based on your hook: before it scrolls to top during navigation it sets it to |
@timneutkens I disabled the hook, and configured scrolling with css. The result was really not the same, compared with the hook enabled using a nightly version of Next right before the change landed. For the next two weeks I’m traveling without any device on hand, but I can provide a reproducer afterwards. Thx for looking into that! |
@timneutkens I spent a bit of time on this problem yesterday.
In fact, the implementation seems to be wrong, as the scroll behaviour "auto" immediately or during scrolling switches back to "smooth" or the globally defined behaviour of the html tag. Local experiments showed that the scrolling behaviour "auto" must be initiated at the start of a route change "routeChangeStart" and must be maintained until a route change is completed "routeChangeComplete". Pre-condition: Summary of the lifecycle:
In the next step I describe the necessary changes
In doRender, where the mounting of Root occurs
In the component Root
Second variant, remember the initial scroll-behaviour defined for a global css html tag
Revert to previous code at the end of onHeadCommit
Probably the identical logic is also necessary in the file (not tested as this is probably due to Next's new layout system)
Furthermore, the function handleSmoothScroll, which is called in scrollToHash (file next/shared/lib/router.ts) is not needed. What do you think, I can provide a pr with those changes? Thx! |
Hi @gurkerl83! I've attempted to reproduce the issue you described with the scrolling behavior, but I'm having issues with finding any issue. You can see this reproduction over here https://nextjs-scroll-repro.vercel.app/ and can see that between the navigations, there is no issues. |
@wyattjoh The issue is when you have two pages (routes), both huge in space. Obviously, smooth scrolling on one page is not a problem and it works. But when you are scrolled very far from the top of page A and then execute a route change to the page B (also very long) during navigation, the page scrolls all the way up from the previous scroll position of Page A to the top (newly loaded page B); this has to be immediate, with "auto" activated until the page loading is finished. The vertical amount of space of a page and where the scroll position is when an navigation attempt is made is really the key here to reproduce the issue. I hope this makes sense. Thx! |
Is it possible to fork my reproduction to create an appropriate reproduction of the issue? |
I think i see this already in your reproducer. Make the sections larger, scroll down in one page and execute a route change to the other page (not a hash change). You will see a scroll during navigation to the top and this is what needs to be immediate. |
@wyattjoh Here is a video with your reproducer in action illustration the problem. I adjusted the height of the sections to make it clear. Imagine when you have larger pages such as blog posts or a e-commerce pages showing dozen of items, changing a route causes a smooth transition to the top, which is really annoying, and this has to be immediate. Screen.Recording.2022-12-01.at.23.57.02.movThx! |
I did the following experiments: repro These are smooth: document.documentElement.style.scrollBehavior = "smooth"
await sleep(0);
document.documentElement.style.scrollBehavior = "auto"
window.scrollTo(0, 0) document.documentElement.style.scrollBehavior = "smooth"
await sleep(0);
document.documentElement.style.scrollBehavior = "auto"
await sleep(0);
window.scrollTo(0, 0) These are instant: document.documentElement.style.scrollBehavior = "smooth"
document.documentElement.style.scrollBehavior = "auto"
window.scrollTo(0, 0) document.documentElement.style.scrollBehavior = "smooth"
await sleep(0);
document.documentElement.style.scrollBehavior = "auto"
await sleep(10);
window.scrollTo(0, 0) Adding It's not claar to me why the following doesn't scroll instantly: document.documentElement.style.scrollBehavior = "smooth"
await sleep(0);
window.scrollTo({
top: 0,
behavior: 'auto'
}); Observations:
I did all the test in chrome. |
Weird this will be instant: html {
scroll-behavior: smooth;
} document.documentElement.style.scrollBehavior = "auto"
await sleep(0);
window.scrollTo(0, 0) And this one seems to be instant even with value set in document.documentElement.style.scrollBehavior = "auto"
await sleep(0);
document.documentElement.style.scrollBehavior = "smooth"
await sleep(0);
window.scrollTo(0, 0)
document.documentElement.style.scrollBehavior = originalValue; It seems that when setting from JS it needs |
The problem might be that html {
scroll-behavior: smooth;
} document.documentElement.style.scrollBehavior = "auto"
document.documentElement.getClientRects() // triggers reflow
window.scrollTo(0) |
@jankaifer I think you have to look at the changes made in #40642 also mentioned in the very first comment of this issue to make sense of it. To set „auto“, then scroll and then reset back to „smooth“ does not force scrolling to do it in „auto“ or immediate mode, these changes execute in a synchronized manner (resetting to smooth does not wait for scroll to finish). Looking at your PR, for me it is not clear why getClientRects triggers a reflow, is this documented somewhere? When it would be a repo of mine, I would rather resolve it directly, instead if embedding API calls which might provide this kind of side effect. Anyway, thx for spending time looking at the problem! I think it’s time for a Next developer to respond to these findings, to get the problem resolved, hopefully in one of the next minor releases. |
I've read the whole thread and I've seen that commit. html {
scroll-behavior: smooth;
} document.documentElement.style.scrollBehavior = "auto"
window.scrollTo(0) This will be smooth. And triggering reflow before Forcing reflow is a little-known hack that is sometimes necessary. For example for triggering FLIP animations. I don't know about any proper docs except this empty mdn page. |
My testing only found the issue in Chrome. Firefox and Safari correctly did not have this reflow bug. I've tested @jankaifer's PR (seen here) and it looks like that fixes the problem. I'm going to recommend we merge that PR as it doesn't depend on router events which are not available in the new router in the app directory. |
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. |
Verify canary release
Provide environment information
Operating System:
Platform: darwin
Arch: x64
Version: Darwin Kernel Version 21.6.0: Sat Jun 18 17:07:25 PDT 2022; root:xnu-8020.140.41~1/RELEASE_X86_64
Binaries:
Node: 16.13.0
npm: 8.1.0
Yarn: 3.2.3
pnpm: N/A
Relevant packages:
next: 12.3.1-canary.3
eslint-config-next: N/A
react: 0.0.0-experimental-8951c5fc9-20220915
react-dom: 0.0.0-experimental-8951c5fc9-20220915
What browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
Describe the Bug
@timneutkens @cramforce The following commit completely disables smooth-scrolling- #40642. We use the following custom hook here to trigger the scroll-behaviour we want. We do not have anything else like a global css which sets the scroll-behaviour on html.
The scroll-behaviour becomes non-deterministic in version 12.3.1-canary.4, the previous version 12.3.1-canary.3 works perfectly. The latest release 12.3.1 is also affected.
Can you please provide feedback on how to enable scroll-behaviour using the hook again?
Thx!
Expected Behavior
Identical behaviour like in 12.3.1-canary.3
Link to reproduction
I will not create a reproducer for things y break; and smooth-scrolling is something which broke a few times in the past.
To Reproduce
Use the hook from above in _app.
The text was updated successfully, but these errors were encountered: