Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reloading the page causes the scroll position to be reset to the top. #3471

Closed
ghost opened this issue Jun 25, 2018 · 12 comments · Fixed by #5080
Closed

Reloading the page causes the scroll position to be reset to the top. #3471

ghost opened this issue Jun 25, 2018 · 12 comments · Fixed by #5080

Comments

@ghost
Copy link

ghost commented Jun 25, 2018

Version

v1.4.0

Reproduction link

https://capu-zennio.github.io/nuxt-scroll-position-bug/index.html.

Steps to reproduce

1.- Load the Nuxt site.
2.- Scroll down.
3.- Refresh the page.

What is expected ?

The scroll position should be the same as it was before reloading.

What is actually happening?

The scroll is reset to the top of the page.

Additional comments?

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].

This bug report is available on Nuxt community (#c7284)
@ghost ghost added the cmty:bug-report label Jun 25, 2018
@XanderLuciano
Copy link

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

@ghost
Copy link
Author

ghost commented Jul 17, 2018

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.

@XanderLuciano
Copy link

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.

@manniL
Copy link
Member

manniL commented Jul 17, 2018

I can't reproduce the problem with my setup (Website, Repo). It only resets on a hard reload/cache reload. When pushing F5 or CTRL+R, the scroll position keeps the same.

Maybe this is browser dependent? I've tested it in the latest FF so far.

@XanderLuciano
Copy link

Unable to reproduce also using the manniL's website on the latest version of Chrome and Chrome canary.

@ghost
Copy link
Author

ghost commented Jul 18, 2018

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:

  • Opening https://developmint.de In Firefox (v61.0.1):
    • When reloading normally, the scroll position stays the same.
    • Deleting the cache resets the scroll to the top.
  • In Chrome (v67.0.3396.99), no matter what I try, the scroll position always stays the same, as it should. I've tried deleting the cache, unregistering the service worker, etc.

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.

@manniL
Copy link
Member

manniL commented Jul 18, 2018

@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.

@ghost
Copy link
Author

ghost commented Jul 19, 2018

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.

@Atinux Atinux added this to To do in Bugs 🐞 Aug 7, 2018
@sebmor
Copy link

sebmor commented Aug 17, 2018

@Capu-zennio Good temporarily solution

@manniL
Copy link
Member

manniL commented Aug 17, 2018

@Capu-zennio Not a core contributor, but I'd love to see a PR for it ☺️

BTW: scrollRestoration is supported in all major browser except Edge (and IE ofc). source

@stale
Copy link

stale bot commented Oct 31, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale label Oct 31, 2018
@stale stale bot closed this as completed Nov 7, 2018
Bugs 🐞 automation moved this from Open to Fixed Nov 7, 2018
@lock
Copy link

lock bot commented Dec 7, 2018

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.

@lock lock bot locked as resolved and limited conversation to collaborators Dec 7, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Bugs 🐞
  
Fixed
Development

Successfully merging a pull request may close this issue.

4 participants