Scroll Position seems to not work in my app

I am trying to work with scroll behavior in the vue-router in my vue app, but it does not appear to be working properly, or, at all. I set up the scrollPosition function like so in my router, as per the docs:

scrollBehavior (to, from, savedPosition) {
  if (savedPosition) {
    return savedPosition
    } else {
      return { x: 0, y: 0 }
    }
  },

…but the app is still not working properly.

What is happening is I have a grid of articles that span a distance greater than the height of the browser window. If I scroll to the top of the grid and click on the first article, I am then taken to that article. If I do not scroll in the article and return to the grid using the back button, then the grid of articles stays where it was, but if I scroll down the article to the end, then either use the back button I made in the app or use the browsers back button, then I return to the grid, but the grid has also been scrolled down to the bottom as well. It is neither remembering it’s last position or going back to the starting position.

I ultimately want it to remember it’s last position, but scrolling back to the top would be ok as well…in fact, I just want it to work at all.

The only thing I can think of it that there is some CSS somewhere that is causing an issue, but I don’t know where or how to begin looking for the issue.

This is the CSS on my html and body to prevent the default bounce of over-scrolling in the browser:

html, body {
  height: 100%;
  overflow: hidden;
  margin: 0;
  padding: 0;
}

…in Safari this works nicely, by moving the bounce to the main section but not letting the fixed header and footer menus bounce as well. In chrome everything stops bouncing, but I’ll take it, until the browsers make this default behavior better, and/or more easily controllable.

Here is the CSS on the main section, which is the area that is not resetting it’s scroll position properly:

main {
  height: calc(100vh - 128px);
  width: 100vw;
  margin: 0;
  padding: 0;
  margin-top: 64px;
  margin-bottom: 64px;
  overflow: scroll;
  -webkit-overflow-scrolling: touch;
  z-index: 0;
}

…the calc value is to place the main section fully in between the fixed header and fixed footer, so as to allow me to create components that can fill the entire remaining space and adjust size accordingly and always fill said space, regardless of the height/width of the device browser window. This design pattern also necessitates the use of overflow: scroll to allow for the overflowing of content to be accessible upon scroll.

Any thoughts on the matter would be appreciated :slight_smile:

R

Are you using history mode?

1 Like

yes, I am.

export default new Router({
  mode: 'history',
  scrollBehavior (to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition
    } else {
      return { x: 0, y: 0 }
    }
  },
  routes: [
    {
      path: '*',
      redirect: '/'
    },
    //moar routz, etc...

Hi @LinusBorg, coming back around to this now…in the current app I am building scroll position does not seem to work for what I have built, and I don’t know why.

I have a fixed <header>, a <main> section with overflow-scroll, and a fixed <footer>, and the main section is where my routes are changing. If I scroll to the bottom of the main section, then change routes, I start at the bottom of the next route, and if I then scroll to the top of the main section in the current route, then I switch routes again, I am back to the top of the next route.

It seems that scroll position on my <main> section does not reset itself, but rather stays in the same scroll position as the previous route, even with the above code in the router.

I found this in an issue comment on GitHub and I wonder if it might be related to my issue:

Unfortunately it doesn’t work in our case. The reason is - side panel and main panel both have overflow: auto; and thus window.scrollTo does nothing.

Here is the link to that GitHub issue:

I’m trying to wrap my head around what’s going on and maybe there is a solution somewhere in that thread or somewhere else…

Thanks for any help that you can give me :slight_smile:

R

Are you not relying on scrolling from the top most element, like <body> but instead using a sub element that takes up the full screen height/width and applying a overflow on that instead and hiding body/htmls overflow? If so, I dont think the router scroll capability will just automatically know what element it needs to scroll and by default I assume applies window.scrollTo but if you have that over ridden and rely on scrolling of another element instead (Which is common in certain types of absolutely positioned layouts) then I dont think that will work

1 Like

yes. I have a layout with a fixed header and footer, and the scrolling occurs in the main section. Is there a way to control scrolling of a sub-section of the page then, rather than the whole window? Are there libraries or plugins or directives, etc…that can do that? I’m looking around but I’m not even sure what I’m looking for…

How to do it within the scrollRouter position functionality on another element, no clue off the top of my head. You could listen for a route change within your component that houses the <main> element, and everytime the route changes, detected in that component, do a scrollTo on that element specifically.

1 Like

k, so after doing a bunch of googling and making confused faces I now have this in my vue instance, which at least resets scroll position on my <main> section:

new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App },
  methods: {
    fixCrappyScrollBehavior () {
      document.getElementById('main-content').scrollTop = 0
    }
  },
  watch: {
    $route () {
      setTimeout(this.fixCrappyScrollBehavior, 250)
    }
  }
})

…so now I need to figure out how get to the previous scroll position back as well on certain pages, which will probably be tougher…

but…

at least…

progress… :slightly_smiling_face:

I don’t know if this is any help, since I use keep-alive on all my components where I want to restore scroll on a overflow-div, but I just save last scroll position in a variable before route change, and scroll back to this position on activation:

activated() {
    document.querySelector('.content').scrollTop = this.scrollposition
},
beforeRouteLeave(to, from, next) {
    this.scrollposition = document.querySelector('.content').scrollTop
    next()
}