Allow disabling of automatic scroll restoration on navigation


#1

Note: This has already been proposed on whatwg mailing list. The consensus so far has been that it is a important problem to fix and I have incorporated several round of feedback on the API design. I am hoping to cast a wider net here and get additional feedback (and hopefully buy in) from other vendors and interested parties.

TL;DR

Add a new boolean attribute to history in order to allow web developer to opt out of automatic scroll restoration that occurs during navigation. This allows developers to get rid of their brittle hacks around it. We are very interested to solve this issue in blink and I have a working patch behind a flag.

Problem Summary

History spec does not specify the scroll position persistence and restoration and leaves it up to user agents to implement. All major browsers provide scroll restoration functionality for both traditional document navigations and entries create via History API (i.e., pushState, and replaceState). Despite its prevalence there is currently no reliable and cross- browser solution for developers to opt out of this behaviour or control any of its aspects.

The default scroll restoring behaviour works well for document style web sites but it is often not appropriate for single-page web applications. Precise controlling of the scroll restoration is particularly important for single-page applications due to the following reasons:

  1. They may be re-constructing the page content onpopstate every time and often asynchronously. The user agent does not know when page is fully constructed so it may attempt to restore scroll position on a partially constructed page which has an incorrect size causing the scroll to land on an unintended incorrect position due to clamping.

  2. They may want to provide consistent scroll restoration regardless of how the page is entered e.g., via history navigation or vanilla links clicks.

  3. They may want to control the details of visual transition between UI states for example using a specific scrolling animation to transition instead of an instant jump, or even restoring scroll position of inner scrollers.

Proposed Solution

We propose to modify History API and make it possible for web authors to explicitly disable the default scroll restoration behavior. This is achieved by adding a new attribute, scrollRestoration, to window.history. This new attribute can take two values: ‘auto’, ‘manual’ with ‘auto’ being the default.

Setting scrollRestoration to a new value updates the current entry in history session. Also any future entry that is added to history session for the same document will use this new scrollRestoration value. However, changing this value does not impact any previous entries in sessions history including those that belong to the same document. Furthermore, any navigation to a new page with a different document resets the scrollRestoration to its default value.

Note that this ensures that changes to scrollRestoration only affect entries that will be created for the same document (e.g., entries created using pushState, or due to fragment navigation).

enum ScrollRestoration {
    "auto",
    "manual"
};

partial interface History {
     attribute ScrollRestoration scrollRestoration;
};

scrollRestoration: Indicates whether the user agent should restore scroll position when traversing to this entry. Anytime this attribute is modified the current entry in joint session history should be updated to reflect the change.

Open issues

I am keeping track of open issues on github repo. Here are the current ones:

  1. Expose recorded scroll position
  2. Consider supporting scale restoration as well

#2

References


#3

What’s up with there being two threads for this?


#4

Aaah, it is a mistake and should be removed. This was my original post which was blocked as spam (I think it had too many links to my github). It has now been re-posted.