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

Adjust Scroll Restoration Behavior for Reloads #10597

Open
Udassi-Pawan opened this issue Sep 4, 2024 · 23 comments
Open

Adjust Scroll Restoration Behavior for Reloads #10597

Udassi-Pawan opened this issue Sep 4, 2024 · 23 comments

Comments

@Udassi-Pawan
Copy link

What is the issue with the HTML Standard?

Currently, the page is typically scrolled to the last saved position during reloads, forward, back, and current page navigations.

While scroll restoration is beneficial for forward and back navigations—where users generally expect to return to where they were—it can lead to inconsistencies in the case of reloads. This is because the content of the page might have changed since the last load, making the previously saved scroll position irrelevant or even misleading

Also hitting the refresh button might be implying that user may want to view the page anew. Preserving the scroll position might counteract this intent by taking them to a part of the page they didn't intend to revisit immediately.

So would it not be best to omit scroll restoration in the case of reloads, while we can keep it intact for other history navigations.

@toyoshim
Copy link

toyoshim commented Sep 4, 2024

I discussed this with @Udassi-Pawan in a chromium code review here;
https://chromium-review.googlesource.com/c/chromium/src/+/5815673
and I'm supportive of this idea.

Also It seems Safari already takes this behavior for usual reload and the same URL navigation as reported here; https://g-issues.chromium.org/issues/330207607#comment11

@annevk Do you know the current contact for the Firefox in this area?

cc: @jeremyroman for chromium side help from the spec POV.

@skobes-chromium
Copy link

There is a separate but related question of whether scroll restoration should be done when users focus the address bar and hit Enter (essentially an explicit navigation to the same URL as the current page).

Chrome currently treats this the same as pressing the Reload button, doing scroll restoration in both cases. But prior to 2016 they were handled differently (restoration only on Reload).

I would support restoring the pre-2016 behavior, either by enshrining it in the spec, or by resolving here that the behavior of pressing Enter in the address bar is up to the user agent.

@php4fan
Copy link

php4fan commented Sep 4, 2024

There is a separate but related question of whether scroll restoration should be done when users focus the address bar and hit Enter (essentially an explicit navigation to the same URL as the current page).

CERTAINLY when focusing the address bar and hitting Enter, scroll restoration MUST be omitted, regardless of what you decide to do on reload. While an argument could be made that, on reload, scroll restoration might actually be desired/expected, it is certainly not the case when hitting Enter from the address bar. The latter is a very explicit request by the user to load the url that is in the address bar, and if that includes a fragment, that includes a specific scrolling position.

Also consider the following use case:
I copy a url which include a #fragment, and I paste it into the address bar, in a tab that is already open, but which I wasn't using or looking at. The url that I paste happens to be, by coincidence, the exact same URL that was currently being displayed. So this is the same as focusing the address bar and hitting Enter. But I am not even aware of that because I just picked a random tab to paste my url into. Obviously, by hitting enter, I expect to be brought to the scrolling position indicated in the URL, not to have the scrolling position restored just because the URL that I have specifically requested happens by pure chance to be the exact same url that was previously loaded in this browser tab or window that I had forgot about for the last few hours.

If you don't make a distinction between (A) focusing the address bar and hitting Enter and (B) pasting or typing a URL into the address bar, resulting in an URL identical to the one that was already there, and then hitting Enter, then (A) and (B) have to be treated equally, and because it would be absolutely inconceivable to treat (B) as a reload, and especially to restore scroll in case (B), then it cannot be restored in case (A) either.

And I don't think that making a distinction between (A) and (B) would make sense, it would lead to all kinds of inconsistencies.

I would support restoring the pre-2016 behavior, either by enshrining it in the spec, or by resolving here that the behavior of pressing Enter in the address bar is up to the user agent.

If something is to be left to the user agent, I think it should be the other way around. Whether or not to restore scrolling on reload is what could be subject to personal preference and it might make sense to leave it to the user agent (which in turn might want to have a setting for that). On the other hand, restoring scroll when hitting enter from the address bar is absolutely insane, so it makes more sense to prohibit that in the standard.

@toyoshim
Copy link

toyoshim commented Sep 5, 2024

I agreed that moving to the top or fragment position rather than scroll restoration is a better behavior for the address bar operation.

On the other hand, it's difficult to have an undefined reload-like navigation only for this case. Today, many modern APIs depend on the navigation type. So, such ambiguous navigation causes chained ambiguity on several specs. That's one of the reasons we needed to change the address bar operation to be aligned with the existing reload.

Also the scroll position is combined with the mobile screen's zoom scale, and "persisted user state" may need to follow the change. I didn't remember what is classified into the "persisted user state" clearly, but maybe form inputs or/and the zoom scale?

For these reasons, I'm supportive to drop the restoration behavior on reloads in general, that includes the address bar operation case.

Another possible choice might be doing a normal navigation rather than reload on the address bar operation. That allows us to keep the current behavior for the reload, and can revert the scroll restoration on the address bar operation. For this case, we may not need the spec change as this may be an implementation specific UX choice.

Let me paste some relevant spec links that I did also in the code review for the discussion.

https://html.spec.whatwg.org/multipage/browsing-the-web.html#persisted-user-state-restoration
This part explains the scroll position as a persisted user state.

https://html.spec.whatwg.org/multipage/browsing-the-web.html#reloading-and-traversing
reload

https://html.spec.whatwg.org/multipage/browsing-the-web.html#updating-the-document
https://html.spec.whatwg.org/multipage/browsing-the-web.html#scrolling-to-a-fragment
explaining the initial scroll position setting forward the page top, or a fragment part

@php4fan
Copy link

php4fan commented Sep 5, 2024

Another possible choice might be doing a normal navigation rather than reload on the address bar operation

The address bar operation is clearly a normal navigation and not a reload. Again, consider the action of pasting a new url into the address bar and then hitting Enter. To compare that to the previous url and then do a reload or a normal navigation depending on whether the two urls are equal or not, is just ridiculous (and it's what Chrome currently does).

When the address bar is focused and the user hits Enter, that means "navigate to this URL". Whether or not that url matches the currently loaded url is irrelevant. And what happened before (i.e., did the user type or paste or edit the url or did they just give focus to it and hit enter?) also has to be irrelevant.

@smaug----
Copy link

Would this apply to reload from the user interface and history.go(0) ? Scroll restoration is an ancient feature, so I wonder if changing history.go(0) behavior might break some sites.

For location bar browsers have different behaviors. In Firefox if there is a fragment included, it is a same document navigation (to that fragment), if not, it is a new load. Not reloading in fragment navigation case is very handy.
Chrome seems to reload always, so looks like it is indeed restoring scroll position.

Browser UI behavior is of course up to the UA, but if we want the spec to change, it would affect history.go(0).

@php4fan
Copy link

php4fan commented Sep 5, 2024

Shouldn't it be the case, that hitting Enter from a focused address bar containing the url X, should always have the exact same effect as clicking a link that links to url X?

@jeremyroman
Copy link
Collaborator

cc: @jeremyroman for chromium side help from the spec POV.

I'm happy to defer to @skobes-chromium on this.

@skobes-chromium
Copy link

I agree with the general principle that browser UI is up to the user agent.

I don't see a compelling reason to change the behavior of history.go(0) or location.reload(). If I understand correctly, these do scroll restoration by default, but the developer has the option to suppress with history.scrollRestoration = "manual".

The idea that address-bar Enter should simply scroll to the fragment in the existing page (same-document navigation) is interesting. I did not realize Firefox did this. It's different from pre-2016 Chrome, which I think was more like a normal document-replacing page load that didn't trigger "reload"-associated behaviors (scroll restoration, invalidating disk cache?)

@toyoshim
Copy link

toyoshim commented Sep 6, 2024

@skobes-chromium
pre-2016 Chrome's address-bar Enter was more "reload"-like than today, but just scroll restoration was missed.
Also, at that point, people expect the same url + enter reloads the page.

In the 2016's change, I modified the addres-bar Enter behavior to be consistent with mobiles' pull-to-refresh behavior, and the purpose was to reduce the number of unnecessary conditional requests from Chrome.
https://engineering.fb.com/2017/01/26/web/this-browser-tweak-saved-60-of-requests-to-facebook/
See the latter part of the Chrome section.

Users can trigger the pull-to-refresh action only at the beginning of the page. So this would not have been a matter on mobiles.

By the way, the article above also said that the reloads on the addres-bar Enter were special for Chrome. So changing it to a normal navigation would be a possible choice? I think people rarely need reload on desktop today, or there are several options to trigger reloads quickly for advanced users, e.g.. Ctrl+R, F5.

@egirard
Copy link

egirard commented Sep 9, 2024

We should also consider the behavior on "hard reload", typically triggered by Ctrl-Reload (or Cmd-Reload, or Ctrl-Shift-R, or probably some combination of ctrl or shift with F5). This "reloads your current page without using cached content".

I'm not confident that everyone calls this "hard reload", but will use that term here for now. If others have a better term for it, please advise.

In my opinion, a hard reload would ignore the current scroll position (since the current scroll position can be considered "cached content"). This would suggest that a "regular" reload could continue to respect scroll position.

Agree with others that URL-navigation should ignore the scroll position.

@Udassi-Pawan
Copy link
Author

Summarising the conversation that we have had so far:

There is consensus on omitting scroll restoration from same-URL navigation in the address bar.

To achieve this, we have two options:

i) Omit scroll restoration from both reload and address bar navigation, making them consistent by not restoring the scroll position in either case.
This way, we avoid the need for an extra reload type specifically for same-URL address bar navigation.

ii) Treat same-URL navigation in the address bar as a normal navigation (without scroll restoration), while preserving scroll restoration for reloads.
This option is more subjective, and there doesn’t seem to be any strong objective reason to favor or reject it.

Any views?

@skobes-chromium
Copy link

skobes-chromium commented Sep 10, 2024

As a first step, I propose we change same-URL navigation in the address bar to be a normal navigation in Chrome. When the URL has a hash fragment, this would scroll to the fragment in the existing page, without loading it from the network.

If I'm reading correctly, this addresses @toyoshim 's original concern about introducing a new navigation type, since we are instead adopting an existing navigation type. Also it aligns us with Firefox, and with @php4fan 's expectation that address bar navigation to url X has the same effect as clicking a link to url X.

I have more hesitation about changing the behavior of F5 / Reload button (either regular or "hard" variants). The intent expressed by that UI is less about navigating and more about refreshing the page content. And there is some value in giving users choice by supporting both behaviors.

@Udassi-Pawan
Copy link
Author

Yeah, this seems like the option with minimal overhead and trade-offs. It also aligns well with existing browser behaviors.
Anyone wanna add something here?

@toyoshim
Copy link

yeah, @skobes-chromium 's proposal sgtm

@csreis
Copy link

csreis commented Oct 25, 2024

I'm in support of @skobes-chromium's proposal as well, and I'm reviewing the change for it at https://chromium-review.googlesource.com/c/chromium/src/+/5896034. Two questions:

  1. Should the address bar behavior change apply to bookmarks as well, per https://crbug.com/40682643? Firefox appears to apply it to bookmarks, such that bookmarks with fragments (and the same URL) do a same-document navigation and scroll to the fragment, and bookmarks without fragments navigate cross-document and scroll to the top. I would be in support of updating bookmark behavior as well.

  2. Can I confirm that same-URL navigations without fragments should replace the current history entry? That seems reasonable to me, but I wanted to call out that this would clear form state and other info as well as the scroll position. That seems consistent with treating it as a new navigation with replacement, though.

Thanks!

@skobes-chromium
Copy link

skobes-chromium commented Oct 28, 2024

Q2: Yes, if we are to align with the behavior of clicking an <a href=...>, then if there is no fragment we should replace the current history entry. This would also invoke beforeunload handlers so the page can warn about unsaved data if it wants to.

If there is a fragment, including an empty fragment (#), then we should just scroll to the fragment.

Here is a test page I made to check how links currently behave: https://output.jsbin.com/motaxeg/quiet

@LiangTheDev
Copy link

LiangTheDev commented Oct 28, 2024

For same url navigation from address bar, Safari seems to behave differently from Firefox.

Safari seems to behave like "navigation to a new document": loads from network whether the url has fragment or not. From end user's point of view, it is the same as pre-2016 Chrome behavior.

Firefox seems to behave like clicking a link: scrolls to the fragment if the url has a fragment and loads from network when the url does not have fragment. This is the same behavior as if the current page were at the url without the fragment. One thing could be a source of complaint: if the page is already scrolled to the fragment, press Enter on address bar, nothing happens.

For @tyoshino's concern, neither behavior seems to require introducing a new type of navigation. It is a choice of navigation to different or same document when url has fragment. I have changes for both approaches in https://chromium-review.googlesource.com/c/chromium/src/+/5896034/17 and https://chromium-review.googlesource.com/c/chromium/src/+/5896034/18.

So, the question is: which behavior is more desirable or feels more natural to the user? Would appreciate your opinions. @skobes-chromium, what do you think?

For @csreis's question of whether same URL navigation should replace current history entry, I was wondering about the same. Don't know whether current entry is replaced or reused internally, external behavior of Chrome, Firefox, and Safari is that no new entry is added to the history. And the spec seems to in favor of replace. Though not exactly about this scenario, in step 11 of https://html.spec.whatwg.org/multipage/browsing-the-web.html#beginning-navigation:

If url equals navigable's active document's URL, and initiatorOriginSnapshot is same origin with targetNavigable's active document's origin, then set historyHandling to "replace".

And in "Note" about history handling behavior https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigation-supporting-concepts:

Other cases that often, but not always, force a "replace" navigation are:

if the Document is not completely loaded; or

if the target URL equals the Document's URL.

@LiangTheDev
Copy link

For @csreis's first question about same url navigation from bookmark, it looks like Chrome and Firefox behave the same while Safari behaves differently.

Safari loads from network whether the url has fragment or not.

Chrome and Firefox loads from network if the url doesn't have fragment, and scroll to the fragment if url has fragment.
When the page is already scrolled at the fragment, nothing happens. This is the complaint in https://issues.chromium.org/issues/40682643.
If we do the same thing for same url navigation from address bar, I could see a similar complaint.

The 2 scenarios feel similar to me: user uses browser UI to explicitly navigate to a url which happens to be the same as current url. It would be better for the behavior to be the same.

@LiangTheDev
Copy link

It seems that we are all supportive of changing Chrome's behavior to not restore scroll position when user enter the same url from address bar. What is not clear to me are the following:

  1. Do we prefer treating it as navigation to a new document or as if it were a click on the page? Or both are reasonable and it is up to the user agent?
  2. Do we prefer consistent behavior for same url navigation from address bar and from bookmark? Or it is also up to the user agent?

@skobes-chromium, @csreis & @toyoshim, could you clarify your view on the above?

@skobes-chromium
Copy link

As-if-click is what I had mind when I wrote #10597 (comment).

I have no strong preference re. bookmarks but would lean toward consistency.

@csreis
Copy link

csreis commented Nov 7, 2024

I'm also in support of "as-if-click," which is consistent with Firefox. That means scrolling to the fragment if there is one, rather than loading from the network.

One thing could be a source of complaint: if the page is already scrolled to the fragment, press Enter on address bar, nothing happens.

Thanks for pointing this out (and that appearing to do nothing was the actual concern for bookmarks in https://crbug.com/40682643). It does seem consistent with the "as-if-click" approach, and hopefully the greater consistency overall will help both the enter-in-address-bar case and the bookmark case. The user can always use Reload if they want to load the page from network again.

I would also support treating bookmarks the same way as enter-in-address-bar, so that they scroll to the requested fragment (and stay there if already scrolled to it).

@LiangTheDev
Copy link

Thanks for confirming. Will change Chrome's behavior to "as-if-click".

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

No branches or pull requests

9 participants