Scroll to top button is a very common UX feature in websites. It's goal is to prevent annoying users forced to scroll back up - especially on mobile devices. In this short tutorial, we'll see how to implement one with css and pure (vanilla) javascript.
The simplest way to get a scroll to top button is to have an html element at the top and a link near the end of your page that calls it:
<div id="scroll-to-top"></div>
<!-- ... -->
<a href="#scroll-to-top"></a>
And this css to make the scroll smooth:
html {
scroll-behavior: "smooth";
}
That's the easiest way to get a scroll to top (I've actually missed this on my original post as Loouis Low pointed out in the comments.)
Result here:
No javascript needed!
Scroll to top button with vanilla js
The previous example works fine but has a serious drawback because after clicking on that link, the anchor #scroll-to-top will show up in the url . We could call the anchor #home. But it'll still be in the url history when the user clicks back.
That's why I prefer to do it in js 😁. Plus js allows much more customization like:
- Show button after the user has scrolled down x % of the page.
- Animate entrance and leave.
The button
Let's just created a simple button with a class of scrollToTopBtn
so we can refer to it in js.
<button class="scrollToTopBtn">TOP</button>
Here are a few CSS properties for the button:
position: fixed;
gets it out of the flow of the page.bottom: 50px;
andright: 50px;
places it at the bottom right corner.z-index: 100;
a large z-index keeps the button on top of every other elements.display: none;
is used to hide it at first.
Detect user scroll
we can detect user's scroll with a scroll
event listener:
document.addEventListener("scroll", handleScroll);
function handleScroll() {
// do something on scroll
}
Show the Scroll to Top button logic
In the handleScroll
function, we'll check whether we need to show or hide the button. We are going to use three element properties:
clientHeight gives us the visible part of an element in its parent.
scrollHeight gives the total height of an element including the overflow part.
The height of the overflow part is the total amount of pixels that can be scrolled. In other words: scrollableHeight = scrollHeight - clientHeight
var scrollableHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
document.documentElement
is the document element. We are using it instead of document
because scrollHeight and clientHeight are elements' properties.
- scrollTop gives the number of pixels scrolled from the top. It's the amount of pixels scrolled by the user.
By dividing scrollTop with scrollableHeight we get a ratio between 0 and 1. 0 meaning the user hasn't scrolled and 1 meaning the user scrolled to the end of the page. This ratio tells us how much the user scrolled.
If we want the scroll to top button to show up after the user scrolled 50% we set a golden ratio of 0.5. And, with an if else statement, make the button visible above and hidden below.
document.addEventListener("scroll", handleScroll);
// get a reference to the button
var scrollToTopBtn = document.querySelector(".scrollToTopBtn");
function handleScroll() {
var scrollableHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var GOLDEN_RATIO = 0.5;
if ((document.documentElement.scrollTop / scrollableHeight ) > GOLDEN_RATIO) {
//show button
scrollToTopBtn.style.display = "block";
} else {
//hide button
scrollToTopBtn.style.display = "none";
}
}
With that the scroll-to-top button appears and hides on scroll.
Scroll to top
There a lot of scrolling examples that use jQuery. But these days it is really easy to do this in pure js with scrollTo:
\\...
scrollToTopBtn.addEventListener("click", scrollToTop);
function scrollToTop() {
window.scrollTo({
top: 0,
behavior: "smooth"
});
}
-
top: 0,
means scroll to 0px vertically. -
behavior: "smooth"
makes the scroll smooth. - there's also a
left
property for horizontal scroll.
And that's it! Here's the final js:
document.addEventListener("scroll", handleScroll);
// get a reference to our predefined button
var scrollToTopBtn = document.querySelector(".scrollToTopBtn");
function handleScroll() {
var scrollableHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var GOLDEN_RATIO = 0.5;
if ((document.documentElement.scrollTop / scrollableHeight ) > GOLDEN_RATIO) {
//show button
scrollToTopBtn.style.display = "block";
} else {
//hide button
scrollToTopBtn.style.display = "none";
}
}
scrollToTopBtn.addEventListener("click", scrollToTop);
function scrollToTop() {
window.scrollTo({
top: 0,
behavior: "smooth"
});
}
Tada 🎉🎉🎉!
Thanks for reading 🥰🥰!! I hope this was of help.
Improvements:
I've tried to keep it simple. Usually I would also toggle a class instead of the display to show a transition animation.
Here's how you could fade up the button:
Top comments (15)
The most minimalist
scroll-to-top
. (Rookie)Thanks for the feedback Loouis 😄!! This is indeed a minimal scroll to top implementation. It's perfect for rookies like u said.
I just want to note that scroll-behavior support is still not optimal caniuse.com/#search=scroll-behavior
And I was thinking of a button that would only appear after a certain amount of scroll and that is not attached to the flow of the page.
But thanks for the insight, I didn't think of this method 😁. Those who want to have a scroll to top with no js would love it!
Why using javascript when you can use only html and css ?
Salut Corentin, maybe because I don't know yet how to do it without js 😅😅. But I'll look up on that. Thx for leaving a comment!
No problem :)
Smooth scroll (example here) is not yet implemented in Safari and some mobiles browsers, so it must be a good reason to keep using js for a couple more months.
Setting display: none removes the button. So you can't click on it.
Setting opacity keeps the button in place and you can interact with it. You can see this in the last example with the display scrolled to the top. Hover the cursor over the location of the button. Note how the cursor changes to a hand shape.
If you happen to have a link under the button the user can't click on it. If the user happens to click on that location (say to interact with a link or highlight text), it will jump to the top of page.
You have to do more than just set opacity to make this non-confusing for a user. I realize this tutorial is meant for beginners, but these are things that a beginner should have brought to their attention so they don't have to unlearn it in the future. Implementation can be left as an exercise for the reader 8-).
Hey John, thx for the precious feedback! I didn't notice that the button was still inside the page 😅. I've increased the translate value from 50 to 100px because it's at 50px from the bottom and its height is 35px so by translating 100px down it's completely out of the screen. Thx again for taking your time to explain this flaw 😁!!!
Nice, thanks for sharing! I was recently wondering about adding a "scroll to top" button on my portfolio site vs. making my header "sticky". On the one hand, it would be nice to add some JS to my site to show that I can incorporate it, but on the other hand, using a sticky header would probably be better performance-wise (which may not matter on my simple portfolio website).
What do you think?
Hey Cory, thanks for reading 😄!! You can definitely use both. I kinda understand why you you want to choose between them. Having a sticky header might make a scroll to top button a bit redundant. But I believe it's ok to use them together especially if the page is kinda long. And btw, I don't think this would create a performance issue. Let's chat on Twitter 🙂!
Very helpful thank you!
Thx for the support buddy 😀😊!! I hope I was clear enough. Don't hesitate to tell me if u'd like me to explain sth 👌.
I really enjoy your tutorials. They are very well documented and cover all the details. Nice work.
Thx a lot Madeline ❤, I still make plenty of mistakes 😇.
Nice work, ljc! I learned a lot of neat tricks and tips about scroll properties. Thanks for sharing!
Much welcome James, thx for reading 😊😊!!