next.js: [NEXT-378] Next 13: Navigation with Link does not scroll up the page

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System: Platform: linux Arch: x64 Version: #1 SMP Mon Sep 19 19:14:52 UTC 2022 Binaries: Node: 16.15.0 npm: 8.5.5 Yarn: 3.2.4 pnpm: N/A Relevant packages: next: 13.0.2 eslint-config-next: 13.0.0 react: 18.2.0 react-dom: 18.2.0

What browser are you using? (if relevant)

Chrome 107.0.5304.87

How are you deploying your application? (if relevant)

Vercel

Describe the Bug

When navigating between pages using Link, the page does not scroll up by default wich is supposed to be the default behaviour of next/link

Expected Behavior

The page scrolls up when switching pages unless I manually disable this feature of next/link

Link to reproduction

https://beta.otpfy.com/

To Reproduce

  • Access https://beta.otpfy.com/
  • Scroll down until you see the “Get started for free” button
  • Click the given button
  • Check that when navigating to the auth page the scroll is preserved and not scrolled to the top

:

From SyncLinear.com | NEXT-378

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 54
  • Comments: 73 (19 by maintainers)

Commits related to this issue

Most upvoted comments

Confirming the scroll restoration not working after upgrade to NextJS 13.1 just today.

For now can be fixed by adding a <ScrollUp /> component to your page:

'use client'

import { useEffect } from 'react'

export default function ScrollUp() {
  useEffect(() => window.document.scrollingElement?.scrollTo(0, 0), [])

  return null
}

i think problem isn’t solved yet. Right?

The next problem is when you press the browser’s back button: Normally the previous HTML page should be displayed in the same scroll position as before. But the page hangs and blocks for a moment, and then the document jumps back to the top of the page. This is very inconvenient when I’m scrolling through a list of, for example, blog posts and then go to the details of a post and then want to go back to look at the next blog post. I find this behavior very annoying.

why is not on the top priority list.

Scroll behavior and back navigation are on the list of things to investigate further. E.g. there’s this PR: #43845. As of right now it’s expected that navigation scrolls to the nearest common layout that changed, this ensures that when you’re navigating between tabs it keeps the relevant changed content in view and doesn’t start from the top of the page. #43845 changes that behavior to scroll to the top of the page if the element stays in the viewport while at the top of the page. This behavior is relevant because in the new router you can soon create e.g. a tab UI similar to what you can see on https://app-dir.vercel.app/ssg where you wouldn’t want it to scroll to top on interactions.

Please be patient while we work through the backlog of all app related issues, it’s in beta for a reason and to reiterate it’s not meant to be used in production yet.

Please don’t post comments like “same issue”, “It’s still an issue in version x.x.x”, “is this resolved yet” they’re not constructive.

I am still experiencing the scroll position being preserved on the 13.2.2 canary. It appears in an /app directory, in a server component.

I thought this scrolling behavior was a bug at first and rolled back to the pages directory because of it.

Scrolling to top after clicking a link seems like it should be the default behavior to match “web” expectations and maybe you should have to opt into this scroll to nearest layout container div behavior if that’s what you want?

Or maybe rather than scrolling to the top of layouts inner content, it should scroll to the top of the layout itself to give context to the page navigation? So ie if you are just using a root layout it would always just scroll to the top of the entire pag. If your nested layout includes tabs it would scroll to show the tabs also.

@this-Cunningham This is expected behavior.

We do this to show the changed content on navigation because it’s bad UX if you click a link and nothing changes.

this scrolling should be opt-in/out because you are making assumptions about the design of the layout with the current implementation

Also this is happening even when navigating to the page with the layout from another part of the site with a different layout. Assuming that the user wants to jump/scroll to the children of the layout on any navigation is a strange assumption.

https://github.com/vercel/next.js/issues/47475

Thanks for checking the reproduction. I can reproduce this locally. It’s confusing it works correctly in the CI. Because we have added this exact reproduction into our test suite.

I’ll look into this.

I am trying with version 13.1.6, but personally I am still experiencing problems using a basic layout with fixed navbar to navigate between pages that share the same layout. I don’t understand if with https://github.com/vercel/next.js/pull/43845 merged this case should already be covered or it is still a work in progress.

I just wanted to point out that I do not see a scroll property on the beta docs. It is not in props or legacy props. 🤷

I’m also on 13.1.1, and it doesn’t seem like Next.js is adding any elements with data-nextjs-scroll-focus-boundary.

I actually have a relatively simple website that reproduces this behavior if it helps.

Running document.querySelectorAll('[data-nextjs-scroll-focus-boundary']) on a few pages returns empty NodeLists. I also tried things like removing display: flex from body to no avail.

Hi the div data-nextjs-scroll-focus-boundary is not longer available… This issue is very annoying and I can’t understand why is not on the top priority list. Maybe it happens only for certain configuration or styles?!

For me, the scroll does work but it doesn’t scroll all the way up. Seems like it’s scrolling to the top, minus the height of the sticky navbar. When I remove the header, it scrolls just as expected. Anyone know a solution to this?

edit: it also works perfectly fine when just reloading the page, with the header/navbar still there.

We’ve landed #43845 which changes the heuristic to scroll to top when the element is in the viewport when scroll position is at the top. If it’s not in the viewport when at the top of the page it’ll scroll to the changed element.

@ Fredkiss3 Thanks for your answer 😃 Yes you are right, but what if I don’t want to? Normally I want it to just scroll all the way to the top when clicking on another page. That should be clarified.

To all: please post a Sandbox with reproduction of your issue, without it these “I’m having this issue in my app as well” comment are useless, just give a thumbs up to the original post to not spam all the people following this issue!

If I am not mistaken, scrolling still doesn’t work with page params. Navigating from /mypage?page=1 to /mypage?page=2 using the <Link> component doesn’t trigger any sort of scrolling and the page remains at the same location even if the content has changed.

Hey, are you still having the same problem after the latest canary release ? You can install it with next@canary.

I’ve seen that they removed the unnecessary divs appearing inside children of layouts in this PR : #43717

Hi, I’m using the latest 13.0.7-canary.6 version but I have the same issue

@JanKaifer and/or @timneutkens, Maybe not completely related to this issue, but will there be a way to opt-out from the auto-scroll feature? Let’s say your page lives inside a modal (with position: fixed) and is using the same layout as the current page, you’d want to maintain the current scroll position. Now, the page scrolls up to the top of the layout.

The problem with that workaround is that it’ll also be triggered if you use the back button, which is generally not the desired behaviour – the “native” behaviour is to to restore the previous scroll position.

It’s a viable interim solution if you don’t mind that though.

Experiencing this on 13.2.4, links from a scrolled page result in a scrolled destination page. if I add scroll={true} to the <Link /> the problem goes away but this should be the default behavior according to the docs. Also If I use router.push(url) the problem goes away.

I did notice the default experimental scrollRestoration value is false but changing this doesn’t seem to do anything either.

The modal-type UI will be covered by parallel routes and interception which will allow you to create a page / layout that layers on top of the current view with correct scroll behavior.

+1

This affects the back button with both the pages and app directories for me and breaks a fundamental part of the browsing experience.

Hi, using pages you can add:

experimental: {
   scrollRestoration: true,
}

in the experimental section of your next.config.js file to support the back button restoration.

Thank you, I added that to the repro, and I’m able to reproduce this now. Will look into it.

For what it’s worth, this is reproducible on the app playground, which has neither of those.

I don’t know, they added this feature because it seemed really nice (that’s what I know, but maybe I’m wrong), but it seems like it requires the creation of a new react API to do so. What I would have liked from them is that they don’t include the scroll restore functionality before it is implemented by react.

(sorry for my broken english)