next.js

How can I implement a "Back to top" button?


I try to implement a "Back to top" button to my website which is written with Next.js 15.3.1. But the button does not work. It seems that the scrolling events are not fired properly.

I set the state initially to true for testing. The button shows up but does not scroll to top.

"use client";
import { useState, useEffect } from "react";
const BackToTopButton = () => {
const [isVisible, setIsVisible] = useState(false);

// Show button when user scrolls down 200px
useEffect(() => {
    const toggleVisibility = () => {
        if (window.scrollY > 200) {
            setIsVisible(true);
        } else {
            setIsVisible(false);
        }
    };

    // Add scroll event listener
    window.addEventListener("scroll", toggleVisibility);

    // Clean up event listener on component unmount
    return () => window.removeEventListener("scroll", 
  toggleVisibility);
     }, []);

   // Scroll to top function
   const scrollToTop = () => {
    window.scrollTo({
        top: 0,
        behavior: "smooth",
    });
  };

  return (
    <>
        {isVisible && (
            <button
                onClick={scrollToTop}
                className="back-to-top"
                aria-label="Back to top"
            >
                ↑
            </button>
        )}

        <style jsx>{`
            .back-to-top {
                position: fixed;
                bottom: 30px;
                right: 30px;
                width: 50px;
                height: 50px;
                border-radius: 50%;
                background-color: #0070f3;
                color: white;
                font-size: 24px;
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                border: none;
                box-shadow: 0 4px 14px 0 rgba(0, 118, 255, 0.39);
                transition: all 0.3s ease;
                z-index: 1000;
            }

            .back-to-top:hover {
                transform: translateY(-5px);
                box-shadow: 0 6px 20px rgba(0, 118, 255, 0.23);
            }
        `}</style>
    </>
    );
    };

    export default BackToTopButton;

Layout:

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
    <html lang="en">
        <body>
            <Navigation />
            {children}
            <Footer />
            <BackToTopButton />
        </body>
    </html>
);
}

Solution

  • The problem was the height defined for the body.

    The body height was defined as height: 100%, with this parameters the scroll event does not work, even if the page is scrollable.

    The problem is that when this element is constrained to exactly 100% height of the viewport, it can affect: