In this tutorial, you will learn in a few short steps how to create a scroll to top button with CSS inset
shorthand and vanilla JavaScript.
Scroll to top button can be very helpful for websites with lots of content, pages with infinite scrolling, or mobile devices with a small screen that can cause the content scroll to extend.
You can follow along with this tutorial by forking this template.
Step one, create the button
To create a scroll button, use an anchor tag with href="#"
this makes the browser return to the top of the page when clicked, or you can use a custom Id to return to a specific part of the page.
<a href="#">scroll-to-top</a>
Step two, position and style the button
To make the button position fixed relative to the viewport, you need to set position: fixed
on the anchor tag. When the element position is fixed, it gets removed from the normal document flow and then positioned with top, right, bottom, and left properties relative to the viewport.
Although, there is a shorthand for positioning properties called inset
.
Inset works just like margin shorthand, which is used to set margin-top, margin-right, margin-bottom, and margin-left all in one.
syntax
inset: top right bottom left
When auto is used as a value for inset, it considers that value omitted.
Therefore you can use inset like the one below to position your button in the bottom right corner of the viewport.
inset: auto 2em 2em auto;
To put things together, add a class scrollToTopBtn
to the anchor tag and style your button like the one below.
.scrollToTopBtn {
color: #f2f2f2;
background-color: #151515;
text-decoration: none;
border-radius: 25px;
position: fixed;
outline: none;
z-index: 100;
padding: 0.75em 1.5em;
inset: auto 2em 2em auto;
}
Step three, make the button responsive
Now the scroll to top button is styled, placed correctly, and it works. But there is a problem, the button always is visible. To fix that you need to use JavaScript to hide and show the button according to page scroll.
To do that, first, get the button and store it in a variable.
const scrollToTopBtn = document.querySelector(".scrollToTopBtn");
Then get the root element of the document for the offset values.
const rootElement = document.documentElement;
Next, you should register an event listener on scroll event to calculate the button visibility status.
const handleScroll = () => {}
document.addEventListener("scroll", handleScroll);
The handleScroll function will be called every time the user scrolls.
After that, you need the total number of pixels that can be scrolled, and to get that inside the handleScroll function, you need to subtract scrollHeight by clientHeight to get the total amount of pixels that can get scrolled.
const scrollTotal = rootElement.scrollHeight - rootElement.clientHeight;
Now that you have the maximum number of pixels that can be scrolled, you need to divide it by the amount the page has been scrolled to get the scrolled ratio between 0 and 1. Using scroll ratio you can condition the location that you want to hide and show the button. The closer you get to 1, the more the user has to scroll before seeing the button.
if ((rootElement.scrollTop / scrollTotal) > 0.25) {
// Show the button
scrollToTopBtn.classList.add("isVisible")
} else {
// Hide the button
scrollToTopBtn.classList.remove("isVisible")
}
Finally, to make it work, you first need to add opacity: 0;
to the scrollToTopBtn class to hide the button on page load. Then add class isVisible with opacity: 1;
to the button when the page scroll passes the ratio you chose. Last but not least, add transition: all 250ms ease-in-out;
to scrollToTopBtn class for animating the button.
.scrollToTopBtn {
color: #f2f2f2;
background-color: #151515;
text-decoration: none;
border-radius: 25px;
position: fixed;
outline: none;
z-index: 100;
opacity: 0;
padding: 0.75em 1.5em;
inset: auto 2em 2em auto;
transition: all 250ms ease-in-out;
}
.isVisible {
opacity: 1;
}
Step four, fix unwanted clicks
When scroll to top button is hidden, it still can be clicked, which is not supposed to happen. To fix that problem, add pointer-events: none;
to class scrollToTopBtn to ignore the click event and add pointer-events: auto;
to class isVisible to bring back the click event to the button when it's visible.
.scrollToTopBtn {
color: #f2f2f2;
background-color: #151515;
text-decoration: none;
border-radius: 25px;
position: fixed;
outline: none;
z-index: 100;
opacity: 0;
pointer-events: none;
padding: 0.75em 1.5em;
inset: auto 2em 2em auto;
transition: all 250ms ease-in-out;
}
.isVisible {
pointer-events: auto;
opacity: 1;
}
Step five, add smooth scroll to the page
Now scroll to top button works perfectly still, you can add a nice touch to your website with smooth scroll. To do that, just add scroll-behavior: smooth;
to the html tag.
html {
scroll-behavior: smooth;
}
To conclude
Scroll to top button is a simple yet useful feature that can improve user experience of your website drastically. In this tutorial, I showed you how to build scroll to top button with just a few lines of code without any library. You can see and play with the final code at NexusCode.online
Top comments (9)
Nice one. An interesting yet mostly unknown property of classList is that classList.toggle accepts a second argument to force a toggle state, so your code can be reduced:
To improve the performance, you can consider debouncing the scroll handler also.
In your code, the handler function is called every time the user scrolls the page by a few pixels. This could mean the handler function is called many times per second if you scroll quickly through the page, which is not necessary.
I speak about using debouncing in the following post, if you would like to learn more:
Add a smart 'back to top' button to your website 👓🔝
Rob OLeary ・ Apr 27 ・ 9 min read
Hello ! Don't hesitate to use colors in
A few years ago I realized it as a plugin in vanilla.js
insert the following line before the closing body tag:
<script data-color=blue src="scrolltotop.js"></script>
The file scrolltotop.js:
A little trick you can do to remove the overhead of a scroll listener is make trigger line and use IntersectionObserver to see if it's on the screen or not.
Something like this
bravo amir
Thank you
good
Thank you