Closed jakearchibald closed 2 years ago
This came up in discussion with @annevk as well; it slipped out of my brain before I could file it. Thanks for finding this and bringing it up.
The desire for symmetry between scroll and focus is indeed what makes this hard. A quick fix would be to add a scrollReset
option which only applies to push/replace/reload (or maybe only push??). And maybe that's the right thing to do. But if we want to take a step back the picture gets more complicated...
The cross-document nav experience is:
The current navigation API default experience for same-document navs is:
We've been treating focus restore as something that we can't do by default, because of the problem of identifying the "same" DOM element. That seems like a safe bet to me. But we could probably fix the scroll reset/restore behavior.
Proposal:
scrollReset: "after-transition"
or "manual"
, default "after-transition"
. This applies to push/replace.scrollRestoration: "after-transition"
to apply to reload. This might be a bit difficult since same-document "reloads" are basically no-ops right now, but hopefully we can try to make it work.These are both compat-impacting changes. They would bring us to
The proposed navigation API default experience for same-document navs is:
which is close to the cross-document nav experience.
Scroll resets on push/replace
The case I'm unsure about is hash-change navigations.
I'm happy with scrollReset
as an option. The only reasons I thought about rolling them into one option is that scroll resetting is a little bit like a restoration, but it's restoring it to 0,0. You never get resetting and restoring happening on the same navigation.
The case I'm unsure about is hash-change navigations.
If you call transitionWhile()
on a hashchange navigation, you are opting out of the usual navigate-to-a-fragment anyway. (This is why a lot of the demo code has if (!e.hashChange)
.)
Whereas, if anyone was using the hash to store information that was not a target element (e.g., UI state like which tab was open) they might want resetting behavior...
So I think it would be OK.
You never get resetting and restoring happening on the same navigation.
That's a good point, and it would be nice to unify. However:
{ scrollRestoration: "manual", scrollReset: "after-transition" }
. It's harder if they're combined; you need do to { bikeshed: e.navigationType === "traverse" || e.navigationType === "reload" ? "manual" : "after-transition" }
.These are not very strong objections, so if we can think of a good name it still might be better to combine.
I can't think of a good name either. Given the above, it seems fine for them to be seperate options.
The default focus behaviour is to reset focus, which is appropriate behaviour if the page is changing significantly, but not in cases like tabbed navigation.
This behaviour was decided in https://github.com/WICG/navigation-api/issues/202 to match MPA behaviour.
However, it seems like current scroll behaviour is out of step with this intent. In a regular MPA, when you navigate via either push/replace, scrolling is reset to 0,0. It feels like this should happen here too.
I'm not sure if this should be rolled into the current scroll option, or whether it needs a separate
scrollReset
option.