kit: Page scroll position not reset to top on navigation (regression)
Describe the bug
When navigating to a new page, if you are already scrolled partway down the page, the next page load will keep the current scroll position and not scroll back to the top.
I believe this broke with next-193. When I install next-192, this does not happen – navigating to a new page always scrolls to the top, just like regular browser navigation.
Reproduction
Init the SvelteKit demo project. Add the following paragraph in about.svelte
after the last paragraph.
<p>Go <a href="/">home</a></p>
Make the browser window small enough so that the page scrolls and scroll to the bottom of the page. Click the Home link. The Home page loads, but does not scroll to the top (i.e. the nav bar is not visible).
.
Tested in Chrome and Firefox on Windows 10.
Logs
No response
System Info
System:
OS: Linux 4.19 Ubuntu 20.04.1 LTS (Focal Fossa)
CPU: (4) x64 Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz
Memory: 7.79 GB / 12.40 GB
Container: Yes
Shell: 5.0.17 - /bin/bash
Binaries:
Node: 14.17.0 - ~/.nvm/versions/node/v14.17.0/bin/node
Yarn: 1.22.5 - /usr/bin/yarn
npm: 8.1.1 - ~/.nvm/versions/node/v14.17.0/bin/npm
Browsers:
Chrome: 89.0.4389.90
npmPackages:
@sveltejs/kit: ^1.0.0-next.193 => 1.0.0-next.193
svelte: ^3.34.0 => 3.44.1
Severity
serious, but I can work around it
Additional Information
No response
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 39
- Comments: 82 (25 by maintainers)
Links to this issue
Commits related to this issue
- Rolling back SvelteKit version to fix scrolling issue on page load (https://github.com/sveltejs/kit/issues/2733) — committed to sbutler-gh/manyworlds by sbutler-gh 3 years ago
- fix: scrolling when navigate TODO: remove when it will be fixed: https://github.com/sveltejs/kit/issues/2733 — committed to artegoser/artegoser-site by artegoser 4 months ago
These are great comments! This was my situation and what worked for me:
I have two independently scrolling panels in the
__layout.svelte
file:The
sidebar
element contains the navigation and the<main>
element contains my content. (The content in the<main>
element is the part whose scroll position needs to be reset to the top when a user navigates to a new page.) The issue for me was when I would scroll down one page and then click on another page in the navigation, then the scroll position of the content in the<main>
element would remain scrolled down the page. Borrowing some of the ideas posted above, I was able to fix it by adding theafterNavigation
hook in my__layout.svelte
file, like this:Since the scroll position of the content in the
<main>
element is what needed to be reset, I referenced the<main>
element inside theafterNavigation
hook and reset its scroll position.I hope that helps someone else.
This fixed it for me:
I created a reproduction repo that you can access here.
I uploaded a demo in Cloudflare Pages. Here is a demo functioning correctly. When you scroll to the bottom of the page and click on the link, you arrive at the top of the new page.
If I add the following css, the bug appears:
You can see a demo of the bug here. Now when we scroll to the bottom of the page, when we click the link we no longer arrive at the top of the new page, but stay somewhere in the middle.
It’s a bit hacky, but I got around it by adding the following to my root
+layout.svelte
file:I have a PR in the works that tries to address this problem. It might not be the right solution but I would appreciate any feedback on it.
The solution involves checking if
html
andbody
are scrollable, and provides an alternative HTML attribute such asdata-sveltekit-main-scrollable
so the developer can easily tell SvelteKit where the main scrolling area.Yup, this is a known issue. Sveltekit doesn’t know which area to scroll if it’s not the
window
. https://github.com/sveltejs/kit/pull/8723 attempts to resolve this by adding an attribute you can use to specify the main scrolling area, but it might not be the most clean solution.I can reproduce this issue with the given repository. The native
scrollTo
function that is used to scroll to the top does not work if the rootElement in the __layout.svelte hasoverflow: auto;
andmax-height: 100vh;
. In the repository @akkie provided it is caused by the ‘Drawer’ component. So something like this:in the _layout.svelte prevents the native scrollTo function to work properly (https://stackoverflow.com/questions/1174863/javascript-scrollto-method-does-nothing)
However I’m not quite sure if SvelteKit can do anything about that as this issue is caused by CSS inside the SvelteKit App.
I bumped into this issue on my personal repo, using sveltekit
1.5.0
and svelte3.54.0
here’s a minimal reproducible sample https://github.com/crowdozer/svelte-kit-scroll-test happens on brave and chrome, haven’t tried others
the gist is this inner “page” div never scrolls on navigation
my workaround has been to put this in the root layout, now it works fine
Adding a timeout to the window scrollTo worked for us:
@raymclee for now, downgrade to 1.0.0-next.192. It’s only 1 version back so you shouldn’t be missing much (changelog)
Still broken on Firefox. Seems to work on Chrome.
Thanks @s3812497. I’d consider that a workaround, not a bug fix. But appreciate you pointing to that code.
I’m here to report that I’m seeing this issue on the sveltekit sverdle demo (as well as my site) when I use
scroll-behavior: smooth
on firefox version112.0.2 (64-bit)
when I usescroll-behavior: smooth
on thehtml
.experiencing this while using height:100% on both html and body. can’t really remove those because those are already fixed for 100vh in mobile brower issue.
We noticed we had this issue as well; after checking we saw we were using
height:100vh;
on a div we replaced it formin-height:100vh;
and this stopped happeningI’m still facing this issue in the Svelte 3.48.0 on chrome and firefox. Until the fix comes out I’m using the
onMount
function withwindow.scrollTo(x-coord, y-coord)
.Looks to me like setting
scroll-behavior: smooth
breaks scrolling back up on page switch in Firefox, too, as reported by another @AaronNBrock.Here’s my dirty fix in
+layout.svelte
:In my case, scroll behavior is only broken when navigating from root to another page, and only on the initial load. Refreshing the page will then scroll to the top. I’m running SvelteKit 2.3.2 and Svelte 4.2.8.
I tried many of the suggested fixes in this thread, but the only one that worked for me was using the following, or minor variants (e.g. binding to an element and scrollIntoView(), not checking nav type, etc.). The timeout is necessary, and setting the scroll behavior breaks it again.
However, that fix can result in a content flash that’s a bit annoying on some loads due to the nature of setTimeout(). Inspired by that fix, the following also works for me and doesn’t result in any content flashing.
Seems odd, since as far as I can tell, svelteKit natively does something very similar (see here).
I have a similar problem. When a navigate from the root page to a details page, the scroll position is not reset. My suspicion is that this may be caused by nested layouts, but I did not verify this.
I use the following snippet in my
+layout.svelte
to workaround this bug by forcing a re-render when the URL changes.I can’t seem to reproduce this on the same version of Firefox (macos). https://stackblitz.com/github/s3812497/sveltejs-kit-2733?file=README.md
Can you reproduce it using the repository I’ve shared, or provide your own reproducible repository?
It functions the same way people are describing the iOS issue in that it only appears when I apply the ’scroll-behavior: smooth’. I was able to reproduce it with a fresh install of the sverdle demo by only editing the style.css to add the smooth scrolling.
Edit: Here’s the recording:
Still occurring for us on
1.2.1
. (Actually, we were still on^1.0.11
😬 - now up-to-date at^1.2.9
! )We have a workaround inspired by https://github.com/sveltejs/kit/issues/2733#issuecomment-1341340679. Add a div on the top of our scrollable element (you could use an existing element if you have one appropriate) and use
scrollIntoView
:We’re checking
type === "link"
because we don’t want to always scroll to top, for example when we’re usinggoto
withnoScroll
.For us, the problem seems to happen consistently on mobile (iOS Chrome and Safari, at least) but less-frequently on desktop browsers. (No idea why it is intermittent on desktop.)
Our layout is similar to the one nhunzaker describes above. On desktop browsers, most of the time, the new pages load correctly, at the top.
Here’s a demo of the issue:
https://user-images.githubusercontent.com/101564068/214556754-91d4b602-6531-4c80-9439-6e65c58d69b0.mov
Chiming in…
Seeing scroll-to-top behavior not working in iOS/safari, but fine on desktop/chrome.
For iOS/safari at least, it looks like a webkit regression, basically that
scroll-behavior: smooth
+window.scrollTo
(programmatic scrolling) doesn’t work: https://bugs.webkit.org/show_bug.cgi?id=238497 (Additional discussion: https://developer.apple.com/forums/thread/703294)Temporary workaround I’ve implemented is a media query to reset
scroll-behavior
, e.g.@media (max-width: 640px) { html { scroll-behavior: auto; } }
which makesgoto()
calls not dump me halfway down the subsequent page.I’m running into this but only in Firefox. Removing height 100vh/100% from html and body does not fix it for me.
Same here: https://github.com/babakfp/svelte-movies
Video: https://user-images.githubusercontent.com/97315614/168525690-2de734dc-972e-42ec-976c-19b4a42c1855.mp4
Update 1
I removed
height: 100%
onhtml
andbody
, and it fixed. Watch this video:https://user-images.githubusercontent.com/97315614/168527428-06c58837-15c6-4ae8-9f1f-eb0c4ab93576.mp4
Update 2
In update 1 you saw that when I navigate back to the home page, the scroll position starts where I left it (it’s the expected behavior). I added another section of movies and now there is this random behavior that you can see in this video:
https://user-images.githubusercontent.com/97315614/168645174-8eac1e83-7e30-4d4b-bc54-b69197f11c40.mp4
Removing
100vh
from<body>
fixed it for meRemoving
scroll-behavior: smooth;
fromhtml
was what helped me work around the issue for now usingnext.260
with Firefox on MacOS Monterey.@nikosgpet could you maybe provide a minimal repo? I already created a PR and I’d like to check if my changes also fix your usecase.
I think this can be handled by SvelteKit as well. But making something like this configurable would bloat the configuration. In my opinion the page reset should just work without the user having to think about it. However we could improve the page reset logic by checking if there’s a root element in the html body that has a
scrollHeight
> 0 and if so setting it to 0. I’ll try that solution out and create a PR if it is feasible.@nhe23 I just upgraded to
1.0.0-next.224
and the scroll position issue seems resolved. I needed to fix that$page.path
->$page.url.pathname
thing.However I couldn’t upgrade beyond version
1.0.0-next.224
. If I tried1.0.0-next.225
or higher, I get the same sass error as you. I’m not sure what that is, but I’ll debug that separately.Thanks for you help!
@johnknoop can you provide code and instructions for reproducing? as stated earlier, it’s hard to debug without the code
Maybe sveltekit as a cool tool could emit a warning if someone uses scrollTo() and has the given styles applied in the root component. 😃
It’s very hard to debug the issue with just links to a website. It would be great to have a minimal repro (either a github repo or stackblitz link) so we can track this down.
Currently, the code to scroll to top is here. The
if (this.autoscroll)
check is based on whether you’ve calleddisableScrollHandling()
.In my tests of the https://painhas.com website, I can confirm that Kit is calling
scrollTo(0, 0)
, which should scroll to the top. By injecting this code in the console:I cannot reproduce this issue. Scroll position is reset to the top as it should be for me. Im also using MacOS and the current SvelteKit Version (v1.0.0-next.242) and tested with Chrome and Safari using links to different routes (explicitly not “/”). It would be great if someone who has this issue could provide a repository to reproduce and detailed system information.
Fixed for me in
@sveltejs/kit@1.0.0-next.199
.@jgrieger We haven’t changed much in the router since this fix, so I’m guessing the root issue is the same as #2794 (newer). I haven’t found a way around it yet.
I’m having same problem. What is the workaround please?