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?

6 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