https://capu-zennio.github.io/nuxt-scroll-position-bug/index.html.
1.- Load the Nuxt site.
2.- Scroll down.
3.- Refresh the page.
The scroll position should be the same as it was before reloading.
The scroll is reset to the top of the page.
This issue is related to window.history.scrollRestoration
(https://github.com/nuxt/nuxt.js/blob/b022d21bd3df08870171727eab9ad89dc1f9944f/lib/app/router.js#L41). If set to auto
, the bug disappears.
I haven't taken an in-depth look at this, but something inside this file is causing the scroll to be set to [0,0].
Take a look through the scrollBehavior
option: https://nuxtjs.org/api/configuration-router#scrollbehavior
The scrollBehavior option lets you define a custom behavior for the scroll position between the routes. This method is called every time a page is rendered.
By default, the scrollBehavior option is set to:
const scrollBehavior = function (to, from, savedPosition) {
// if the returned position is falsy or an empty object,
// will retain current scroll position.
let position = false
// if no children detected
if (to.matched.length < 2) {
// scroll to the top of the page
position = { x: 0, y: 0 }
} else if (to.matched.some((r) => r.components.default.options.scrollToTop)) {
// if one of the children has scrollToTop option set to true
position = { x: 0, y: 0 }
}
// savedPosition is only available for popstate navigations (back button)
if (savedPosition) {
position = savedPosition
}
return new Promise(resolve => {
// wait for the out transition to complete (if necessary)
window.$nuxt.$once('triggerScroll', () => {
// coords will be used if no selector is provided,
// or if the selector didn't match any element.
if (to.hash && document.querySelector(to.hash)) {
// scroll to anchor by returning the selector
position = { selector: to.hash }
}
resolve(position)
})
})
}
Hi, @XanderLuciano, thanks for answering.
However, scrollBehavior
is only called when navigating between routes. This bug report refers solely to the page's fist load.
How about storing the current scroll offset and then restoring the scroll offset after page load?
// Source: https://codepen.io/patrickkahl/pen/KFmAb
// Store the scroll position in local storage
// but also remove it from storage upon page load
$.fn.scrollPosReaload = () => {
if (localStorage) {
const posReader = localStorage["posStorage"];
if (posReader) {
$(window).scrollTop(posReader);
localStorage.removeItem("posStorage");
}
$(this).click(function(e) {
localStorage["posStorage"] = $(window).scrollTop();
});
return true;
}
return false;
}
$(document).ready(function() {
// Call 'scrollPosReaload()' on page load
$('select').scrollPosReaload();
});
Would need a little modification to use the proper Vue hooks, but should get you most of the way.
Seems like either the scroll position is not saved or is getting wiped on resfresh. In manual mode "you" have to keep track of all the scroll offsets. In auto, chrome keeeps track. So maybe with the help of some plugins like this : https://www.npmjs.com/package/vue-scroll-behavior might help with your use case and/or help with finding the source of the issue.
Unable to reproduce also using the manniL's website on the latest version of Chrome and Chrome canary.
I confirm that @manniL's website doesn't have this problem _when visited on its domain_.
However, it does show the problematic behaviour when run with npm run dev
. Another couple of things to look at:
I'm thinking that this is somehow related to the site being a PWA? The SW is not installed when running on dev mode.
Just to show the bug exists: https://capu-zennio.github.io/nuxt-scroll-position-bug/index.html
This site is a project created with nuxt-create-app
and I only changed the height of the container to 200vh to make it scrollable. If you load it, scroll down and refresh, you'll be sent to the top. If you disable javascript, scroll down and refresh, the position stays the same. This was tested with Chrome and Firefox.
@Capu-zennio You are right. Can also repro this with the link given! (I'd suggest to add it to the actual issue)
Possible that the PWA/SW is a workaround to this problem.
At this moment, I'm just using the following in layouts/default.vue
(since all my pages use it):
mounted() {
if (process.client && window) {
window.history.scrollRestoration = 'auto';
}
},
This seems to fix all the issues and doesn't appear to have any unintended side effects. Either way, I'd prefer it if a mantainer could confirm it before starting a PR, which is why I opened the issue.
@Capu-zennio Good temporarily solution
@Capu-zennio ~Not a core contributor~, but I'd love to see a PR for it :relaxed:
BTW: scrollRestoration
is supported in all major browser except Edge (and IE ofc). source
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
At this moment, I'm just using the following in
layouts/default.vue
(since all my pages use it):This seems to fix all the issues and doesn't appear to have any unintended side effects. Either way, I'd prefer it if a mantainer could confirm it before starting a PR, which is why I opened the issue.