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

fix(nuxt): scroll to top on page navigation when scroll-behavior: smo… #25817

Merged
merged 2 commits into from Feb 22, 2024

Conversation

Chalks
Copy link
Contributor

@Chalks Chalks commented Feb 15, 2024

πŸ”— Linked issue

fixes #25816
fixes #19239

❓ Type of change

  • πŸ“– Documentation (updates to the documentation, readme or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

In Firefox, if you have scroll-behavior: smooth style set on html, navigation between pages doesn't scroll to top (reproduction). The root cause of the problem is that awaiting nextTick in router.options.ts doesn't work in that case. It's not clear to me why since the nextTick implementation doesn't seem to be doing anything too strange. That said, replacing await nextTick with awaiting a setTimeout fixes things. This happens to be related to something being addressed in a currently open PR where both myself and @bernhardberger found that a setTimeout was necessary.

I'll admit I'm not particularly familiar with why nextTick is specifically being called here, but as far as I can tell replacing it the way I did fully resolves #25816.

In addition, I fixed a slight missed edge case, if you click on the same link 20 times in a row that all link to the same page, the next time you click on another link, the 20 hookOnces that you created are all resolved at the same time returning undefined. It doesn't seem to cause any issues, but there's no reason to enter line 45+ if we're not going to scroll anyways when you click the same link.

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have added tests (if possible).
  • I have updated the documentation accordingly.

Copy link

stackblitz bot commented Feb 15, 2024

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@danielroe danielroe merged commit 0152cf4 into nuxt:main Feb 22, 2024
34 checks passed
@github-actions github-actions bot mentioned this pull request Feb 21, 2024
@fabianwohlfart
Copy link

fabianwohlfart commented Feb 22, 2024

It seems that const hookToWait = (hasTransition(from) && hasTransition(to)) ? 'page:transition:finish' : 'page:finish' will fire when the page is finished. This internal hook may fire, but the browser may not yet be repainted, therefor the scroll would not work. That's probably why there was a await nextTick(), but this also only waits internally. To wait for the browser to repaint it's common to setTimeout to 0. There is yet another solution, which is to await a requestAnimationFrame like so await new Promise(resolve => requestAnimationFrame(resolve));. From my experience this may be the better solution as rAF is waiting for the browser having capacities to deal with the callback, while setTimeout may dance out of bounce, especially if there is more than one setTimeout on the website.

@CernyMatej
Copy link
Contributor

What @fabianwohlfart mentioned seems reasonable to me .Awaiting a setTimeout 0 indeed causes issues where the scroll happens a few ms after the page actually switches. @danielroe, do you see any issues with replacing it with await new Promise(resolve => requestAnimationFrame(resolve)) ? Based on my testing, it solves the current issue. I believe you may have addressed a similar problem in one of your Twitch streams a few months ago. Was it this one?

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