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>
);
}
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: