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

[NEXT-378] Next 13: Navigation with Link does not scroll up the page #42492

Closed
1 task done
alexvcasillas opened this issue Nov 4, 2022 · 73 comments · Fixed by #45487 or #45782
Closed
1 task done

[NEXT-378] Next 13: Navigation with Link does not scroll up the page #42492

alexvcasillas opened this issue Nov 4, 2022 · 73 comments · Fixed by #45487 or #45782
Assignees
Labels
area: app App directory (appDir: true) linear: next Confirmed issue that is tracked by the Next.js team.

Comments

@alexvcasillas
Copy link

alexvcasillas commented Nov 4, 2022

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

@alexvcasillas alexvcasillas added the bug Issue was opened via the bug report template. label Nov 4, 2022
@semy

This comment was marked as off-topic.

@Fredkiss3
Copy link
Contributor

I think it scrolls up to the nearest <div data-nextjs-scroll-focus-boundary />, this div is automatically created when you wrap your page in a layout. It is supposed to assure scroll restoration within layouts.

you can see in the video below :

Enregistrement.de.l.ecran.2022-11-20.a.00.37.07.mov

@semy
Copy link

semy commented Nov 20, 2022

@ 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.

@Fredkiss3
Copy link
Contributor

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)

@rshaul
Copy link

rshaul commented Nov 21, 2022

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.

@rijk
Copy link

rijk commented Dec 1, 2022

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
}

@trevorpfiz
Copy link

trevorpfiz commented Dec 9, 2022

I have some routes using the Tailwind UI Sidebar Layout where html and body need h-full. So this wasn't working. more details

So I had to use this on those routes:

'use client';

import { useEffect } from 'react';

export default function ScrollUpBody() {
  useEffect(() => document.body?.scrollTo(0, 0), []);

  return null;
}

Not fun.

@Fredkiss3
Copy link
Contributor

Fredkiss3 commented Dec 9, 2022

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

@trevorpfiz

This comment was marked as off-topic.

@rosszurowski
Copy link

For others who come across this issue, I ran into the same thing, but was able to fix it by removing an unnecessary layout. My directory structure looked like:

app/layout.tsx
app/page.tsx
app/blog/[...slug]/layout.tsx
app/blog/[...slug]/page.tsx

In my case, navigating to one of the blog/2020/post-name pages had the page start half-way down, without scrolling back up to the top. Looking at the DOM structure, there were two layers of <div data-nextjs-scroll-focus-boundary /> elements.

I found that removing my app/blog/[...slug]/layout.tsx and wrapping my one-off layout into app/blog/[...slug]/page.tsx instead fixed the issue, since now there was only one layer of layouts rather than two. I moved common layout code into a separate component to share between the two pages where it's needed:

app/layout.tsx
app/page.tsx
app/blog/[...slug]/page.tsx
components/layout.tsx

For a content-based website like the one I was working on, it was a good reminder that nested layouts are probably more meant for apps with truly nested frames rather than a single view. I guess hearing the word "layout" made me think it'd replace my Layout components 1:1.

@valse

This comment was marked as off-topic.

@trevorpfiz
Copy link

I'm using 13.0.7 and the issue is better, but it still does not scroll all the way up if I want it to. It will scroll right below the header.

@davidcm62
Copy link

davidcm62 commented Dec 21, 2022

Same here. We're trying to add a simple layout with a shared header and the main content. On navigation, the page doesn't scroll to the top and the header is always hidden. We're using 13.0.7

@AndrewIngram
Copy link

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
}

Won't this also be triggered when using the back button though?

@metawise

This comment was marked as off-topic.

@mikeyakymenko

This comment was marked as off-topic.

@stevenpetryk
Copy link

stevenpetryk commented Jan 2, 2023

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.

@semy
Copy link

semy commented Jan 2, 2023

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.

stevenpetryk added a commit to stevenpetryk/mafs that referenced this issue Jan 2, 2023
@semy

This comment was marked as spam.

@valse

This comment was marked as off-topic.

@qpavy

This comment was marked as off-topic.

@jessicalc
Copy link

jessicalc commented Jan 4, 2023

I'm on NextJS 12.2.5 and was also observing this problem on pages with shared layouts, where, when I clicked on a Link on Page A to get to Page B, Page B would load scrolled to the position that Page A was at. (i.e. if I was 50% of the way scrolled down on Page A, Page B would load scrolled 50% of the way down!)

Things I tried that didn't work:

  • Not using layouts at all (no dice)

Things that I did to make it work:

That combination seems to have fixed things for my situation. Update: I think scroll={true} doesn't do anything and the real issue is the scroll behavior smooth on the HTML element.

Also wonder to what degree this issue is related: #40719

@qpavy

This comment was marked as off-topic.

@steve-marmalade

This comment was marked as off-topic.

@qpavy

This comment was marked as off-topic.

@jessicalc

This comment was marked as off-topic.

@trevorpfiz
Copy link

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. 🤷

@pogran

This comment was marked as off-topic.

@jankaifer
Copy link
Contributor

jankaifer commented Feb 9, 2023

This shouldn't happen. I tried to reproduce it, but I wasn't able to.
Could you try reproducing the issue here JanKaifer/next-repro-42492
It has a navbar with position: fixed, but it still works as expected.

This is the reproduction that we have tried and that works now.
Could you open a new issue with new reproduction (you can just modify mine) to show what's wrong?

There are a lot of things mentioned in this thread and it would be easier to track them if all of them were in separate issues. Thanks.

@simonecervini
Copy link

This shouldn't happen. I tried to reproduce it, but I wasn't able to.
Could you try reproducing the issue here JanKaifer/next-repro-42492
It has a navbar with position: fixed, but it still works as expected.

This is the reproduction that we have tried and that works now. Could you open a new issue with new reproduction (you can just modify mine) to show what's wrong?

There are a lot of things mentioned in this thread and it would be easier to track them if all of them were in separate issues. Thanks.

Thank you for your work. I tried the new release just now and it doesn't seem to work the same way every time. I also encountered the same problem in your repro (I added a "You are at the top of the page" message in the root layout for easy visualization):

Screen.Recording.2023-02-09.at.11.44.14.mov

Screenshot 2023-02-09 at 11 49 15

@jankaifer jankaifer reopened this Feb 9, 2023
@jankaifer
Copy link
Contributor

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.

@njarraud
Copy link

njarraud commented Feb 9, 2023

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

@ala-garbaa-pro
Copy link

ala-garbaa-pro commented Feb 10, 2023

I solved the issue by calling the 'scrollToTop' on load in 'div':

Of course I add "use client"

const isBrowser = () => typeof window !== "undefined"; //The approach recommended by Next.js
function scrollToTop() {
  if (!isBrowser()) return;
  setTimeout(() => {
    window.document.body.scrollIntoView({ behavior: "smooth" });
  }, 500);
}
const LayoutComponent: React.FC<LayoutComponentProps> = ({ children }) => {

  return (
    <div className={styles._container} onLoad={()=>scrollToTop()}>  <-------------------------
      <Header />
      <div className={styles._page}>{children}</div>

      <Footer />
    </div>
  );
};

export default LayoutComponent;

@kodiakhq kodiakhq bot closed this as completed in #45782 Feb 10, 2023
kodiakhq bot pushed a commit that referenced this issue Feb 10, 2023
fix #42492



## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm build && pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
jankaifer added a commit to jankaifer/next.js that referenced this issue Feb 14, 2023
@LotharVM
Copy link

@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.

@vercel vercel deleted a comment from jankaifer Feb 16, 2023
@timneutkens
Copy link
Member

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.

@xixixao
Copy link

xixixao commented Feb 24, 2023

@timneutkens We also ran into this issue, where the viewport is scrolled down, to a place where the new page differs from the old - but this is super confusing on mobile, and I haven't found a way to disable this behavior. Would be great if we could decide when auto-scrolling should happen and when it shouldn't (ala the scroll prop).

@filipkowal
Copy link

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.

@Huvinesh-Rajendran-12
Copy link

Hi, I am currently seeing this issue in the latest canary release too 13.2.5

@charlielow
Copy link

charlielow commented Mar 14, 2023

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.

@beamercola
Copy link

still seeing this in 13.2.4

@victornevarezcbqa
Copy link

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.

For me it doesn't even work adding scroll={true}

@jankaifer
Copy link
Contributor

@charlielow, @beamercola and @victornevarezcbqa
Could you please open a new issue with minimal reproduction?

@this-Cunningham
Copy link

This happens to me and makes my application pretty unusable in certain screen widths -- Anytime I have a next layout.tsx and I navigate to a page using the layout... If the rendered { children } part of the page are BELOW THE FOLD/ out of the initial viewport the app scrolls down until the children HTML container is scrolled to the very top of the viewport (if there's enough content to do this) ... however, if there is even the smallest sliver of the layout's {children} HTML showing above the viewport/above the fold when navigating.... the application does not scroll down and maintains the correct scroll of zero. This happens to me on all browsers

@this-Cunningham
Copy link

@jankaifer
Copy link
Contributor

@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.

@Arctomachine
Copy link

Encountered this issue in 13.2.3. Not sure what exactly breaks scrolling. Somewhere it works, somewhere else not. In both cases pages from and pages to have identical respective composition and functionality, so it makes narrowing it down hard if possible.

In my project I implemented solution suggested by @ala-garbaa-pro, but modified it to make it separate component with useEffect hook and only include where scroll is broken

@surjithctly
Copy link

surjithctly commented Apr 1, 2023

I'm using router for next/prev pagination. But the scroll to top is not working, so that when clicking next from the bottom of the page, it stays there. The older version had an option to set scroll: true, but I don't know how to set this in /app dir.

  const handleNextPage = () => {
    router.push(`/products?page=${pageIndex + 1}`); // <-- keeps same position. Not scrolling up. 
  };

@rijk
Copy link

rijk commented Apr 1, 2023

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!

@this-Cunningham
Copy link

this-Cunningham commented Apr 3, 2023

@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.

#47475

@github-actions
Copy link
Contributor

github-actions bot commented May 4, 2023

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 4, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: app App directory (appDir: true) linear: next Confirmed issue that is tracked by the Next.js team.
Projects
None yet