17

I have a component like so:

const Milestone = props => {
  const { path, disabled, index, ...rest } = props;

  if (disabled) return <MilestoneCheck disabled />;

  return (
    <Link href={path} passHref>
      <a>
        <MilestoneCheck {...rest} />
      </a>
    </Link>
  );
};

when I click on the 'Link' to go to the next page and than click the back button to go back to where I came from, the page doesn't load at the top but from the last scrolled position. Adding a 'scrollTop' method on route change would feel not very efficient, is there a more elegant solution to always having the page loading at the top?

Aessandro
  • 5,517
  • 21
  • 66
  • 139
  • Have a look on this GitHub issue solution https://github.com/vercel/next.js/issues/28778#issuecomment-1017435267 – Sumithran Jan 22 '23 at 18:32

12 Answers12

19

Ended up doing this in the main app.js file:

  componentDidMount() {
    Router.events.on('routeChangeComplete', () => {
      window.scroll({
        top: 0,
        left: 0,
        behavior: 'smooth'
      });
    });
  }
Aessandro
  • 5,517
  • 21
  • 66
  • 139
16

I had this experience and I tried a lot of ways to get it to work but it didn't. This kind of route change behavior is supposed to happen by default except you're doing something different.

I noticed that after I removed overflow-x: hidden from my html/body tag everything started to work normally.

Try not to use this form of styling in your html/body element:

html, body {
- overflow-x: hidden;
}

You can set a wrapper element's (i.e div) maximum width to 100vw and overflow-x:hidden to archive the same thing.

Divine Hycenth
  • 620
  • 6
  • 11
  • 1
    Thanks bro, I was exploring this error for 1 day, and finally I got here and saw your answer. It helped me and saved my next day. I am shocked that this one line ruined my life for 1 day. – Abidullah Jun 11 '23 at 05:16
  • @Abidullah I'm glad you found it useful. :) – Divine Hycenth Jun 11 '23 at 08:51
13

I had the same issue when my page would not render at the top. In my case in my global.css i had this:

html {
  font-size: 62.5%;
  scroll-behavior: smooth;
}

After removing scroll-behavior: smooth; everything started working as expected.

Noob
  • 2,247
  • 4
  • 20
  • 31
  • 1
    Thank you very much for this solution.Tried many things to resolve this issue. Finally, this worked very silly of us. – Ashfaq nisar Mar 23 '21 at 12:07
  • This was definitely the issue in my case. Thanks. What alternative can one use for smooth scrolling then? – Victor Eke Nov 29 '22 at 16:02
5

A possible cause could be overflow-x: hidden; on one of the root elements: body, html or #__next.

You can try to add min-height: 100% to it or replace it with overflow-x: clip;.

Nikolai Kiselev
  • 6,201
  • 2
  • 27
  • 37
3

I was struggling with this issue for a few days and found the solution.

The issue for some unknown reason was that NextJS has some bug when a global html style is imported. I had html class in my global styles.scss import that was loaded into my main wrapper. Once I removed the html from the import the scrolling issues stopped and pages loaded as they would on a static site.

Found the solution here https://github.com/zeit/next.js/issues/7594

Miguel T
  • 31
  • 4
3

In my case I was using Bootstrap and I had to remove in the bootstrap.min.css file:

:root {
 scroll-behavior: 'smooth'
}
Diego
  • 31
  • 1
2

Another reason pages are not scrolled to the top upon navigation is when the following style rule exists:

html { height: 100%; }

There is a Github issue on this here.

Marnix.hoh
  • 1,556
  • 1
  • 15
  • 26
0

inside of your Page/Layout component import next router

import Router from 'next/router';

// you can then hook into there events

Router.onRouteChangeStart = () => {

};

Router.onRouteChangeComplete = () => {
  window.scroll({
    top: 0,
    left: 0,
  });
};

Router.onRouteChangeError = () => {

};

const Page = props => { 
  return <div>{props.children}</div>
}
0

In my case top: 0 works with behavior: 'smooth, but not with behavior: 'auto'. With default behavior: 'auto' value top: 0 not working, but any other values work e.g:

window.scroll({
  top: 1,
});
artkwi
  • 1
0

This ended up working for me (updated to newest NextJS routing configuration)

Router.events.on('routeChangeComplete', (url) => {
      window.scroll({
        top: 0,
        left: 0,
      });
    });
0

Change next configuration scrollRestoration to false.

experimental: { scrollRestoration: false }

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 22 '23 at 14:24
-7

Wrap your App component with:

<ScrollToTop>
  ... all components there
</ScrollTop>

ScrollTop component:

import React, { useEffect } from 'react';
import { withRouter } from 'react-router-dom';

const ScrollToTop = ({ children, location: { pathname, search } }) => {
  useEffect(() => {
    try {
      window.scroll({
        top: 0,
        left: 0,
        behavior: 'smooth'
      });
    } catch (error) {
      // just a fallback for older browsers
      window.scrollTo(0, 0);
    }
  }, [pathname, search]);

  return children;
};

export default withRouter(ScrollToTop);
demkovych
  • 7,827
  • 3
  • 19
  • 25