DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Back to Back to Top
Andrey K.
Andrey K.

Posted on

Back to Back to Top

One of the most common features for any modern website is the ability to scroll to the top of the page instantly with a help of the "Back to Top" button. Today I want to talk about how to create it and how to improve it a little bit in JavaScript.


Let's say we have a page with a lot of content. At the bottom of the page, before the closing </body> tag, we're creating a simple button with some dummy content (we'll style it later). Let's also create a script file for our button and link in right under the button.

<button class="button-to-top" type="button">To Top!</button>
<script src="script.js"></script>
</body>
Enter fullscreen mode Exit fullscreen mode

To make our button working in a .js file we must first select it using document.querySelector, add an event listener, which would trigger a scroll to the top on click, and write a function which would do the scrolling.

// Selecting a button by its class
const buttonToTop = document.querySelector('.button-to-top');

// Scrolling function
const goToTop = () => {
  scrollTo(top);
}

// Executing scrolling function on click
buttonToTop.addEventListener('click', goToTop);
Enter fullscreen mode Exit fullscreen mode
  • scrollTo() is a method of a Window global object, it can contain page absolute coordinates (0,0) or options (top)

The basics should be working for now. Let's quickly make the scrolling smooth by adding this rule to our CSS file:

html {
  scroll-behavior: smooth;
}
Enter fullscreen mode Exit fullscreen mode

There are countless ways to style a button, I'd like to make our button round and semi-transparent, and also make a transition effect for when our button will be appearing and disappearing. It should also stay fixed in a bottom-left corner, and we need an additional .hidden class for it.

.button-to-top {
  position: fixed;
  right: 20px;
  bottom: 20px;
  width: 60px;
  height: 60px;

  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .9);

  color: #fff;
  background: #333;
  box-shadow: 3px 3px 2px 0 rgba(0, 0, 0, .5);
  opacity: .8;

  font-size: 25px;
  transition: all 300ms;
  cursor: pointer;
}

.button-to-top:hover {
  opacity: .95;
}

.button-to-top_hidden {
  visibility: hidden;
  opacity: 0;
}
Enter fullscreen mode Exit fullscreen mode

I also changed the button text to a 'β―…' symbol. You can modify everything however you want, use an SVG or FontAwesome for a text, for example. For now, a button looks like this:

Button example

Let's work with the script again. We need the button to disappear when we're on top of the page, and appear, if we've scrolled down a bit. To do it, we need to add another event listener in JavaScript, this time - on our browser's window itself. So, when scrolling occurs, and we're, say, 200 pixels down from the top of the document, the button should become visible. We're doing it by adding a .hidden class to a button by default, and we'll be removing it by JS.

<button class="button-to-top button-to-top_hidden" type="button">
β―…
</button>
Enter fullscreen mode Exit fullscreen mode
const buttonToTop = document.querySelector('.button-to-top');

const goToTop = () => {
  scrollTo(top);
};

const showToTopButton = () => {
  if (
    document.body.scrollTop > 200 ||
    document.documentElement.scrollTop > 200
  ) {
    buttonToTop.classList.remove('button-to-top_hidden');
  } else {
    buttonToTop.classList.add('button-to-top_hidden');
  }
};

buttonToTop.addEventListener('click', goToTop);

window.addEventListener('scroll', showToTopButton);
Enter fullscreen mode Exit fullscreen mode

And it's working!
But now let's talk a bit about optimization.


Let's add a little console.log to our showToTopButton function like this:

const showToTopButton = () => {
  console.log('scrolling');
  // ...
Enter fullscreen mode Exit fullscreen mode

Then, when we open our page, then try to scroll for a bit and look into the developer console, we'll see something like this:

Console

And that's a lot of function calls! Although it's not critical here, this is definitely not an optimized behavior. Thankfully, there is a solution for that, and our helper here is Lodash library.

You can add it to your project in different ways (by downloading it, or by using npm), I will use a CDN link and place it before our script in HTML file.

<button class="button-to-top button-to-top_hidden" type="button">
β―…
</button>
<script
  src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"> 
</script>
<script src="totop.js"></script>
Enter fullscreen mode Exit fullscreen mode

There are two modules in Lodash we're interested in - it's throttle and debounce. What they do is make functions to execute only once in a specified amount of time. Let's start with a throttle.

window.addEventListener('scroll', _.throttle(() =>
showToTopButton(), 200));
Enter fullscreen mode Exit fullscreen mode

"_" is an object which holds all Lodash methods. For now we've configured that a showToTopButton function will be invoked only once in 200ms. Let's look at the console.

Throttle console

It's definitely better! Debounce works in a similar way (you can read the official documentation for more info), but in our case the function will be executed only after 200ms after we've stopped scrolling.

window.addEventListener('scroll', _.debounce(() =>
showToTopButton(), 200));
Enter fullscreen mode Exit fullscreen mode

In my personal preference, I prefer debounce for this case.


And that's all I wanted to share today!
Thank you for reading! Feedback and sharing of the post is very appreciated! You can find me on Twitter @ cat__logic

Background by Benjamin Davies

Top comments (2)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.

Classic DEV Post πŸ‘‡

Visualizing Promises and Async/Await 🀯

async await