Nuxt.js: Inconsistent scrollToTop behaviour after update to 1.3.0

Created on 1 Feb 2018  ·  44Comments  ·  Source: nuxt/nuxt.js

Certain pages that were (correctly) jumping to the top of the page after the route changed in 1.1.2 have stopped doing so in the latest release.

Steps to reproduce

  1. scroll down this page: http://next.btmat.org.uk/2012
  2. click on an article excerpt link
  3. see the article render half way down the page

Here's the repo

Both the from page and the to page include scrollToTop: true.

This question is available on Nuxt.js community (#c2378)
bug-report

Most helpful comment

This code does not run when a layout is changed. Think this is a bug.

  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)
    })
  })

All 44 comments

I have the same problem, in some route changes the scroll do not move to the top of the page.

The problem in that cases is the "triggerScroll" event in the scrollBehavior method of lib/app/router.js because the event was not triggered.

For now i am using this code in my nuxt.config.js file:

scrollBehavior (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)
        // view https://github.com/nuxt/nuxt.js/issues/2738
        /*
        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)
        })
        */
        resolve(position)
      })
    }

I've noticed the same thing! Thank you @javialon26 for your snippet! I've tried it, but it does not solve the issue for me.

@davision this snippet is for 1.3.0 version, did you try with that version?

Yep, sorry – I had the wrong version number in the issue title. Have updated it to 1.3.0.

In all version since 1.0

I'm facing the same issue. But the workaround of @javialon26 does not do anything in my setup. I have a custom route on '*' and if the path changes I don't see any possibility of route change.

Same issue here

Same here, not scrolling back to top on newest versions

In my opinion the issue is present if you are changing routes on the same page component via params or query value.

If the route change changes in between different page components the page scrolls up correctly and on history back the scroll position is persisted as well.

@dohomi your opinion is valuable, but wrong.
I have 1.4.0 and only use regular nuxt links to navigate between routes. The position of the page is an issue so when clicking on a footer link to the contact page, the contact page will have the scroll position of the previous

i copy default(https://nuxtjs.org/api/configuration-router) to nuxt.config.js
i found it ok
nuxt1.4.0

router: { scrollBehavior: function (to, from, savedPosition) { if (savedPosition) { return savedPosition } else { let position = {} // 目标页面子组件少于两个 if (to.matched.length < 2) { // 滚动至页面顶部 position = { x: 0, y: 0 } } else if (to.matched.some((r) => r.components.default.options.scrollToTop)) { // 如果目标页面子组件中存在配置了scrollToTop为true position = { x: 0, y: 0 } } // 如果目标页面的url有锚点, 则滚动至锚点所在的位置 if (to.hash) { position = { selector: to.hash } } return position } } }
2018-03-07 4 56 14

@sunlei4076 thanks for sharing. This version of scrollBehavior worked for me too.

nuxt.config.js:

 router: {
    scrollBehavior(to, from, savedPosition) {
      if (savedPosition) {
        return savedPosition
      } else {
        let position = {}
        if (to.matched.length < 2) {
          position = { x: 0, y: 0 }
        } else if (to.matched.some(r => r.components.default.options.scrollToTop)) {
          position = { x: 0, y: 0 }
        }
        if (to.hash) {
          position = { selector: to.hash }
        }
        return position
      }
    }
  }

same issue

same issue

This code does not run when a layout is changed. Think this is a bug.

  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)
    })
  })

As far as I can see none of the suggested workarounds here allow for page transitions.

Using :key on top level element in the page component with dynamic routes fixes scrolling to top when route param changes.

I have it and it doesn't help :/. In my page component I'm having:

<template>
  <div :key="$route.params.slug">

Still, coming off the page component with a dynamic route to a static one, the page is positioned somewhere in the middle.

I am currently solving with v-scroll-to="{el: '#__nuxt' }" in the <nuxt-link> which is ugly but I still didn't find a better solution. How do you guys solving this? To mention, on this page with dynamic route I am sourcing markdown content with markdown-it plugin. Could that be the case?

same issue

This code does not run when a layout is changed.

-> same error :(

@Atinux is this still an issue?

I've been using nuxt Edge and it is an issue usually

Still an issue unfortunately, even on nuxt-edge. This is a pretty big bug IMO. Does anyone have a repo with multiple layouts where scroll to top works?

I spoke yesterday with @Atinux on this and the real issue is vue-router implementation here.

I think we should close / pause this and reference a bug on their side.

@Atinux @pi0 @clarkdo do you know if this is still an issue?

@galvez yes it is

Experiencing same issue. None of the workarounds above worked for me.
scrollBehavior (to, from, savedPosition) { if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } } }

This part works as intended on vue without nuxt.

UPDATE: This solved it for me:
https://nuxtjs.org/api/configuration-router/#scrollbehavior

Copy/pasting the default behaviour into the router.js.

I'd be sad if this fell off the radar – I'm still looking for a solution.

The only acceptable solution for me right now is to use a vue-scrollto plugin. On a default template or _slug I'm having:

mounted() {
    vueScroll.scrollTo('body')
}

It's an ugly hack but currently, the only way to go, sadly.

What do you mean @davision ? Does this simulate browser behaviour?

Cases:

I scroll down a page, I click a router-link - > it goes to the next page on the top directly.

I scroll down the page, I click an anchor link -> it stays on the page if link is in the page, it goes to the other page to anchor link if not

I click back on the browser or a button using router link -> it goes back to the savedPosition from before.

The case is, that you are on one page, scroll down, click on some link in the footer, you go to another page positioned at the bottom. You should come to the top of that new page. But you don't.

Can you not use window.scrollTo(0, 0) then?

That could also work, but then you'll have quite an ugly jump from the bottom of the page to the top.

All: can you try it with updated node modules (npm update/yarn upgrade)? Vue Router had released a new version.

Thanks @manniL – I just upgraded, but sadly the issue is still present (same steps as in the initial post).

I don't think nuxt uses vue-router from your node_modules. I think it's internally built in?
Or perhaps try installing it in your dependancies

@bovas85 Nuxt depends on vue-router, so upgrading/nuking dependencies will update the router package as well :relaxed:

https://github.com/nuxt/nuxt.js/blob/v2.3.2/packages/vue-renderer/package.json#L19

interesting, looks fixed for me

@bovas85 Same here, though https://github.com/nuxt/nuxt.js/issues/4080 ~is~ was still there

I'll try that.

Problem is still reproducable. My guess is because of nuxt-child usage:

<div class="news">
    <NewsList :articleStubs="articleStubs" v-if="$route.name === 'year'" />
    <nuxt-child v-else />
</div>

I think: This happens because there is no real "page transition" in the sense of how it's implemented (as scrollBehavior is governed by the transitions).

/2012 is showing the _year.vue component with the NewsList child.
/2012/05/message-from-prof-hesseling shows the _year.vue component with the nuxt-child child.

As the majority of the problems of this mega-issue is solved, I'll close hear and open a specific one for the problem related to the reproduction of @davidpmccormick

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danieloprado picture danieloprado  ·  3Comments

pehbehbeh picture pehbehbeh  ·  3Comments

msudgh picture msudgh  ·  3Comments

surmon-china picture surmon-china  ·  3Comments

gary149 picture gary149  ·  3Comments