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

Restore scroll position on navigation #43

Open
vlukashov opened this issue Apr 25, 2018 · 17 comments
Open

Restore scroll position on navigation #43

vlukashov opened this issue Apr 25, 2018 · 17 comments
Assignees

Comments

@vlukashov
Copy link

vlukashov commented Apr 25, 2018

As Flow I want Vaadin.Router to support restoring scroll position on navigation in the same way it works in Flow 1.0 so that the future versions of Vaadin Flow could switch to Vaadin.Router instead of the own implementation.

NOTE: react-router does not have any explicit support for scroll position restoration. Their position is that browsers do that by default quite well already: https://reacttraining.com/react-router/web/guides/scroll-restoration

@abdonrd
Copy link
Contributor

abdonrd commented Jun 12, 2018

A reference to the pwa-helpers router: Polymer/pwa-helpers#14

@abdonrd
Copy link
Contributor

abdonrd commented Feb 16, 2019

Any option similar to Polymer/pwa-helpers#14?
Because the event.type is always vaadin-router-location-changed.

@Tansito
Copy link

Tansito commented Jul 30, 2019

do we have some kind of advance for this issue?

@abdonrd
Copy link
Contributor

abdonrd commented Aug 9, 2019

Related example: https://stackblitz.com/edit/lit-element-demo-zejjsv

Steps:

  1. Go to home and scroll to bottom
  2. Click on Sam's profile
    Now the scroll go to the top
  3. Scroll to the bottom and click on Home
    The scroll remains

It seems that the problem is the lazy load of the view using dynamic import().

Now If you uncomment the static imports, it always keeps the scroll:

import './views/home-view.js';
import './views/profile-view.js';
import './views/not-found-view.js';

@vlukashov vlukashov added the enhancement New feature or request label Aug 11, 2019
@abdonrd
Copy link
Contributor

abdonrd commented Oct 22, 2019

There are any workaround with this? Thanks in advance!

@vlukashov
Copy link
Author

One way to reset scroll position would be to add a listener for the vaadin-router-location-changed event:

window.addEventListener('vaadin-router-location-changed', e => {
  window.scrollTo(0, 0);
});

A more elaborate solution would require changes in the Router APIs.
I can think of two different use cases. Does any of that look relevant to your app?

  • if you want to reset scroll position when navigation is triggered by clicking a link, but not when it's triggered by the browser 'back' button
    That would require passing some information from the navigation trigger along with the event so that it's possible to write the code like
    window.addEventListener('vaadin-router-location-changed', e => {
      if (e.detail.trigger === 'click') {
        window.scrollTo(0, 0);
      }
    });
  • if you want to save and restore the exact scroll position for each route
    That would require keeping track of the history of scroll positions for each route and passing that along with the event so that it's possible to write the code like
    window.addEventListener('vaadin-router-location-changed', e => {
      if (e.detail.savedScrollPosition) {
        window.scrollTo(e.detail.savedScrollPosition.x, e.detail.savedScrollPosition.y);
      }
    });

@abdonrd
Copy link
Contributor

abdonrd commented Oct 24, 2019

Thanks for the answer, @vlukashov!

I discard the first option because in many situations we shouldn't scroll to top.

As before I was using the Polymer/pwa-helpers router, the second option seems really interesting! Easy and simple. But I don't have a strong opinion. Also the third looks nice.

@web-padawan
Copy link
Member

Adding a link to the Vue router implementation for reference.

@manolo
Copy link
Member

manolo commented Feb 19, 2020

I think we should use the state serializable object in the pushState API, each time router calls to the method should pass the scroll position, then on popState it can be restored.
Not sure about how to make it configurable by the user in order to configure which routes needs to store/restore scrolling but could be an extra property in the route entry

@web-padawan
Copy link
Member

Note: as discussed today with https://vaadin.com team, we might try history.scrollPosition:
https://caniuse.com/#feat=mdn-api_history_scrollrestoration

It supports all the target browsers of Vaadin 15 (don't be confused with Edge 80, the data seems to be incorrect). IMO this is something worth prototyping to see if it works for us.

@miladkdz
Copy link
Contributor

Just opening up a discussion here: Should we consider the use case of scrolling to an anchor in the page instead of a scroll position?

@abdonrd
Copy link
Contributor

abdonrd commented Apr 13, 2020

Any news here?

@Tansito
Copy link

Tansito commented Apr 27, 2020

Very interested too in this feature and in the scroll to anchor from @miladkdz

@ruanxianzhi
Copy link

Hi, any updates on this issue?

@DeadWisdom
Copy link

DeadWisdom commented May 14, 2020

Not sure if I have a special case, but for me scroll is restored properly on page changes, but when I go to a new page, it doesn't move the scroll position to the top. So I'm pretty confused.

At the very least, if we had something like e.detail.originalEvent with the "vaadin-router-location-changed" event, then we could inspect it and do what we like.

For example, change src/triggers/popstate.js to:

function vaadinRouterGlobalPopstateHandler(originalEvent) {
  if (originalEvent.state === 'vaadin-router-ignore') {
    return;
  }
  const {pathname, search, hash} = window.location;
  fireRouterEvent('go', {pathname, search, hash, originalEvent});
}

And then do something similar in vaadinRouterGlobalClickHandler() as well, now we can see if the event came from a click or popstate, and go from there.

Ultimately, I think saving and restoring the scroll position should be a top priority. I've used the router in a few places, and this issue is mysteriously present or not, and I can't figure out why. When it is present, it is a debilitating user experience.

@MuuKojima
Copy link

Hello, any updates?👀

@abdonrd
Copy link
Contributor

abdonrd commented Jul 20, 2020

It's not ideal, but we have a simple patch to deal with it here: IBM/pwa-lit-template#1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants