Add a Debounced Scroll-To-Top Button to Your Site
Published: 2024-05-06 | Updated: 2024-05-16It only takes a few lines of code to add an unobtrusive button to your site that, when clicked, takes visitors back up to the top of the page. The button shouldn’t just always be there, however. There are some rules to follow about when it should make itself available.
- The button should not show until a visitor has scrolled down a certain distance
- The button should be hidden while the visitor is scrolling down the page
- It should show itself with a simple and smooth animation / transition if the visitor declares intention to scroll up
- But if we mistake the intention and the visitor indeed scrolls further down the page, the button should hide with a smooth CSS animation.
A tall order? Really not so bad. Here’s the code to make it happen.
First, some markup. It’s as simple as it gets.
<button id=scrollToTopButton>↑</button>
and here’s what the code above, our button, will look like in the browser
Now let’s give it some style by adding some CSS
#scrollToTopButton {
background: none;
font-size: 2em;
border: 2px solid darkorange;
color: darkorange;
width: min-content;
padding: 0 0.25em;
cursor: pointer;
/* position it near the bottom of the screen
where it's easy to get to on mobile and generally
out of the way
*/
position: fixed;
bottom: 1em;
right: 1em;
/* make sure it sits on top of other content */
z-index: 100;
/* set it up to move into and out of view and
to fade in and out as needed. Start with the
button hidden off screen and transparent
*/
opacity: 0;
transform: translateY(100px);
transition: all 0.5s ease;
}
/* The CSS needed when we want the button to show */
#scrollToTopButton.show {
opacity: 0.8;
transform: translateY(0);
}
And finally, this bit of Javascript will watch for window scroll events and decide whether to apply the show
class to our #scrollToTopButton
based on how far the visitor has scrolled and in which direction they are currently headed.
let previousScrollPosition = window.scrollY,
timeout = 0,
debounceThreshold = 150,
scrollThreshold = 150,
scrollToTopBtn = document.getElementById("scrollToTopButton"),
rootElement = document.documentElement;
// smoothly scroll to the top of the browser window
function scrollToTop() {
// Scroll to top logic
rootElement.scrollTo({
top: 0,
behavior: "smooth"
});
}
if (scrollToTopBtn !== null) scrollToTopBtn.addEventListener("click", scrollToTop);
window.onscroll = () => {
// don't bother with any of this if there is no button
if (scrollToTopBtn === null) return
// clear any previous timeout
if (timeout !== 0) clearTimeout(timeout);
// then set a new one
timeout = setTimeout(() => {
const currentScrollPosition = window.scrollY,
scrollingDown = currentScrollPosition > previousScrollPosition,
scrollingUp = !scrollingDown,
isTimeToShow = currentScrollPosition > scrollThreshold;
previousScrollPosition = currentScrollPosition;
if (scrollingDown) scrollToTopBtn.classList.remove('show');
else if (isTimeToShow) scrollToTopBtn.classList.add('show');
else scrollToTopBtn.classList.remove('show')
}, debounceThreshold);
};