2.5.3
Sorry for no minimal reproduction - I have honestly no idea where to start with this, or even whether it is a bug in vue-router (I suspect it is).
The ONLY place we have managed to reproduce it is on our live website. Not locally, not on staging environments, just here: https://samknows.com/
The bug:
Scroll handler should have taken you to the top of the page
You're not at the top of the page
Here is my router code right now:
const router = new VueRouter({
mode: 'history',
scrollBehavior: (to, from, savedPosition) => {
console.log(to, from);
if (to.name.startsWith('products') && from.name.startsWith('products')) {
return null;
}
return savedPosition || { x: 0, y: 0 };
},
routes,
});
As you can see in the console, the from route is wrong. What could be causing this? Why is it only happening in some environments, and what can I give you to help?
Sorry for vagueness.
Nice animation 😎
A minimal repro would help us. If it depends on the environment, that's quite unusual and unfortunately for you, probably unrelated with vue-router. Maybe the server is adding some headers? I don't know. You could try setting up a simple repro pushing it to that server and then downloading the resulting html file to check it against the staging server.
Thanks!
Heh, it's quite unusual and I can't see how it can be related to _anything_ - it just shouldn't be happening! However, the to and from objects both being the same, and the from object being wrong - can anything outside of vue-router cause that to happen?
Can't really make a minimal repro without replicating it locally :( I will carry on trying to replicate this and figure out what's causing it. Have already sunk a couple days into it, and it's basically just a link.
😩
I was thinking that you could try testing that minimal repro on the server (not the whole app), maybe you see the difference that way
Our staging environment is running on exactly the same server and it isn't happening there, usually. A few deploys back, it was happening on staging, but it went away when I added the console.log.
I'm closing this for the moment, come back if you get more information 🙂
I met the same problem. Does any body know why?
BTW, NICE Animation!
absolutely no idea. worked around it in the end:
scrollBehavior: (to, from, savedPosition) => {
// This is the workaround
if (to.name === 'products' && from.name === 'products') {
return savedPosition || { x: 0, y: 0 };
}
if (to.name.startsWith('products') && from.name.startsWith('products')) {
return null;
}
return savedPosition || { x: 0, y: 0 };
},
Hi there,
I'm facing a similar issue where scrollBehavior is not working. I think it is due to the fact that window.scrollTo doesn't properly work if you have stricky div elements, andor peculiar nested CSS.
I found a workaround using Element.scrollIntoView.
In my case the following code solved the issue:
scrollBehavior: (to, from, savedPosition) => {
// very bad, maybe better use a Navigation Guard?
document.getElementById('app').scrollIntoView();
return null;
}
_(tested only with Chrome so far)_
Maybe this bug could be re-opened to make sure scrollBehavior can handle this scenario. Ie: if a String is returned it should be considered as an Element's id, therefore scrollIntoView should be applied instead of scrollTo.
_edit: minor fixes_
thanks @lordgordon your comment was very helpful .. I use it in a Global After Hook like this and it works well:
// scroll to top on routes navigation
router.afterEach((to, from) => {
document.getElementById('app').scrollIntoView()
})
For anyone still getting this issue;
I had an overflow: auto on the html tag. Removing it fixed the issue!
I know it been a while. But here is what i do
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
const isHash = to.hash ? to.hash.split('#') : undefined
if (isHash) {
let tmp = setTimeout(() => {
document.getElementById(isHash[1]).scrollIntoView()
clearTimeout(tmp)
})
}
return null
}
},
setTimeout is import for the change of micro task. It will be execute at the end
This works for me to simply scroll to top for every route:
const router = new VueRouter({
mode: 'history',
routes: [...routes],
scrollBehavior () {
document.body.scrollTop = 0; // For Safari
document.documentElement.scrollTop = 0;
},
});
@wuestkamp that will break the expected scroll position behaviour when pressing the back button, though
Most helpful comment
Hi there,
I'm facing a similar issue where
scrollBehavioris not working. I think it is due to the fact thatwindow.scrollTodoesn't properly work if you havestrickydiv elements, andor peculiar nested CSS.I found a workaround using Element.scrollIntoView.
In my case the following code solved the issue:
_(tested only with Chrome so far)_
Maybe this bug could be re-opened to make sure
scrollBehaviorcan handle this scenario. Ie: if a String is returned it should be considered as an Element'sid, thereforescrollIntoViewshould be applied instead ofscrollTo._edit: minor fixes_