Search code examples
javascriptnext.jsnext.js13nextjs-dynamic-routing

Scroll-to-Top Behavior is not working in Next.js when opening a new page via Link component


In Next.js, I'm facing an issue where when I click on a link to open a new page, the new page opens at the same scroll position as the previous page. For example, if I'm on a product listing page and I have scrolled down to view the last product, when I click on that product, the product details page opens with the scroll position still at the bottom.

I would like the page to scroll to the top when opening the product details page. How can I achieve this scroll-to-top behavior in Next.js?

here is the possible solutions that I try

Try 1

import { useEffect } from 'react';
import { useRouter } from 'next/router';
const ProductDetails = () => {
    const router = useRouter();
    useEffect(() => {
        const handleRouteChange = () => {
            window.scrollTo(0, 0);
        };

        router.events.on('routeChangeComplete', handleRouteChange);

        return () => {
            router.events.off('routeChangeComplete', handleRouteChange);
        };
    }, [router]);

    return <>
        // product details code goes here
    <>;
};
export default ProductDetails;

Try 2

import { useEffect } from 'react';
import { useRouter } from 'next/router';
const ProductDetails = () => {
    const router = useRouter();
    
    useEffect(() => {
        window.scrollTo(0, 0);
    }, [router.pathname]);
  
    return <>
        // product details code goes here
    <>;
};
export default ProductDetails;

Try 3

import { useEffect } from 'react';
import { useRouter } from 'next/router';
const ProductDetails = () => {
    const router = useRouter();
    
    useEffect(() => {
        window.scrollTo(0, 0);
    }, []);
  
    return <>
        // product details code goes here
    <>;
};
export default ProductDetails;

Try 4

useEffect(() => {
   // the top id defined on the container of layout which is navbar
   const topElement = document.getElementById("#top");
   topElement?.scrollIntoView({ behavior: "smooth" });
}, [router.pathname]);

The above solution worked for other route but when it comes to dynamic route e.g. /products/product/[slug] it doesn't worked even i add the slug in useEffect dependency array

Note: also try the code directly into that component where i want the screen to move on top but still didn't achieved what i want.

Edited: supported code example added


Solution

  • So after exploring a lot, I came across a solution that made me laugh when I saw it.

    The problem was not with the Next.js components. It was the problem with the predefined CSS in global.css file.

    By default, Next.js global.css contains a lot of CSS. It also defines CSS for the body and HTML tags as shown below:

    html,body {
      max-width: 100vw;
      overflow-x: hidden;
    }
    

    After removing the overflow-x: hidden from the html/body tag, everything started to work normally as expected.

    So, I am thankful to @divine for his answer on another Stack Overflow question that referred to the same issue here is the link to his answer.