Scroll Behavior

When using client-side routing, we may want to scroll to top when navigating to a new route, or preserve the scrolling position of history entries just like real page reload does. vue-router allows you to achieve these and even better, allows you to completely customize the scroll behavior on route navigation.

Note: this feature only works if the browser supports history.pushState.

When creating the router instance, you can provide the scrollBehavior function:

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return desired position
  }
})

The scrollBehavior function receives the to and from route objects. The third argument, savedPosition, is only available if this is a popstate navigation (triggered by the browser's back/forward buttons).

The function can return a scroll position object. The object could be in the form of:

  • { x: number, y: number }
  • { selector: string, offset? : { x: number, y: number }} (offset only supported in 2.6.0+)

If a falsy value or an empty object is returned, no scrolling will happen.

For example:

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

This will simply make the page scroll to top for all route navigations.

Returning the savedPosition will result in a native-like behavior when navigating with back/forward buttons:

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

If you want to simulate the "scroll to anchor" behavior:

scrollBehavior (to, from, savedPosition) {
  if (to.hash) {
    return {
      selector: to.hash
      // , offset: { x: 0, y: 10 }
    }
  }
}

We can also use route meta fields to implement fine-grained scroll behavior control. Check out a full example here.

Async Scrolling

New in 2.8.0

You can also return a Promise that resolves to the desired position descriptor:

scrollBehavior (to, from, savedPosition) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({ x: 0, y: 0 })
    }, 500)
  })
}

It's possible to hook this up with events from a page-level transition component to make the scroll behavior play nicely with your page transitions, but due to the possible variance and complexity in use cases, we simply provide this primitive to enable specific userland implementations.