Next.js link doesn't render with page scrolled at the top

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?

29 thoughts on “Next.js link doesn't render with page scrolled at the top”

  1. 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);
    
    Reply
  2. Ended up doing this in the main app.js file:

      componentDidMount() {
        Router.events.on('routeChangeComplete', () => {
          window.scroll({
            top: 0,
            left: 0,
            behavior: 'smooth'
          });
        });
      }
    
    Reply
  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

    Reply
  4. 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.

    Reply
  5. 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>
    }
    
    Reply
  6. 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,
    });
    
    Reply

Leave a Comment