How to add a back-to-top button on your WordPress website

Landing website pages have been all the rage for a while now and although many of them come with a great design they can also come with a caveat: long body heights. This usually means that after users are done going through our awesome content they are forced into a scrolling sprint back to our website’s header in order to examine more navigation options (which also kinda means our landing page should have more interesting calls to action, but that’s a different story).

One way to mitigate this terrible experience and improve our website’s user friendliness would be to make our header sticky (which we’ll cover in another tutorial), but that’s something that’s not always desirable. Another way, one which we’ll cover in this tutorial, is to add a so-called “back to top” button which stays fixed as we scroll down and smoothly transitions us back to the very top when it gets clicked. This kind of “scroll to top” behavior is so necessary in some use-cases that iOS even has it embedded as a feature in pretty much the core of the OS (by tapping the status bar).

Let’s go ahead and see how simple it is to add this kind of functionality to any website with a simple button.

Our button’s requirements

We’re going to start, as always, by listing our requirements; what we need to accomplish. Thus, the button must:

  1. Appear only when the user has scrolled enough so that its existence is justified.
  2. Hide itself if the user manually scrolls up into that threshold again.
  3. Always remain visible after the threshold and follow along as the user scrolls.
  4. Get us smoothly back to the very top when it’s clicked.

Markup and styling

The HTML we’ll need is extremely simple: just a button element. Go ahead and open your WordPress (child) theme’s footer.php file and right before the body element closes add the following:

<button class="button-top">↑</button>
footer.php

Of course the icon is up to you, I chose a simple up arrow entity for brevity.

If we refresh the page right now we should see an ugly button sitting below our website’s footer, so let’s give it some style; in our (child) theme’s stylesheet:

.button-top {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 100;
  width: 60px;
  height: 60px;
  border: 0;
  border-radius: 2px;
  box-shadow: none;
  background: #145474;
  color: #fff;
  font-size: 26px;
  line-height: 20px;
  text-align: center;
  cursor: pointer;
}
style.css

And here’s how it should look:

light

Pretty cool so far, but before we go any further let’s add a few more styles. We want to start by having the button hidden, and then we’ll define a new class which we’ll later enable via JavaScript and turn it back to visible.

.button-top {
  ...previous code
  pointer-events: none;
  opacity: 0;
  transition: opacity .18s ease;
}

.button-top-visible {
  opacity: 1;
  pointer-events: auto;
}
style.css

Making it functional

All righty, we’ve got our button styled and ready (and invisible), time to actually make it work. First thing we need to do is to actually make it smooth scroll back to the top when it’s clicked. Let’s add that code in our theme’s scripts file (make sure jQuery is loaded!):

jQuery(function ($) {
  var $buttonTop = $('.button-top');

  $buttonTop.on('click', function () {
    $('html, body').animate({
      scrollTop: 0,
    }, 400);
  });
});
scripts.js

Now every time the button is clicked, it’ll scroll us to the very top of our website within 400 milliseconds (feel free to adjust the timing to your liking).

If we hadn’t required that the button starts hidden we’d be done right now. But we want to show it only when the user has scrolled enough to actually be useful.

What we need for this is to tap into the scroll event of the browser’s window object and check if we’re scrolled enough from the top; if we are, we’ll add that .button-top-visible CSS class and show it. If we aren’t we’ll remove it (and consequently hide the button).

So, the actual event we’re after is probably the scroll event as the name implies, but how are we going to figure out how much we’ve scrolled so far? Let’s see what jQuery offers.

.scrollTop(): Get the current vertical position of the scroll bar for the first element in the set of matched elements.

Well, that sounds exactly what we need. Let’s amend our code and do just that.

jQuery(function ($) {
  var $window = $(window);
  var $buttonTop = $('.button-top');

  $buttonTop.on('click', function () {
    $('html, body').animate({
      scrollTop: 0,
    }, 400);
  });

  $window.on('scroll', function () {
    if ($window.scrollTop() > 100) { // 100 is our threshold in pixels
      $buttonTop.addClass('button-top-visible');
    } else {
      $buttonTop.removeClass('button-top-visible');
    }
  });
});
scripts.js

Perfect! Inside our scroll event listener we check for a simple condition, if we’re scrolled more than 100 pixels we’ll show the button, if not, we’ll hide it!

Advanced: Optimizing for performance

Our button is ready at this point, it fulfills all the requirements we’ve specified when we started, but I couldn’t possibly end this tutorial without bringing awareness to the fact that our code, although elegant, comes with a performance headache: the callback function we provide to the window’s scroll event listener is going to be called an inordinate amount of times, because the scroll event by nature is fired every time the scroll position changes (which is, again, a lot lot lot more than we need).

We don’t really need to check every millisecond or so. We’ll be good sports and debounce our function so that it gets called only once we’ve stopped scrolling and X amount of time (let’s say every quarter of a second) has passed since the last call.

A naïve, quick and dirty approach is the following:

jQuery(function ($) {
  var $window = $(window);
  var $buttonTop = $('.button-top');
  var scrollTimer;

  $buttonTop.on('click', function () {
    $('html, body').animate({
      scrollTop: 0,
    }, 400);
  });

  $window.on('scroll', function () {
    clearTimeout(scrollTimer);
    scrollTimer = setTimeout(function() {
     if ($window.scrollTop() > 100) {
        $buttonTop.addClass('button-top-visible');
      } else {
        $buttonTop.removeClass('button-top-visible');
      }         
    }, 250);
  });  
})
scripts.js

We’re not exactly debouncing here, but it comes very close, and with minimal code (credits go to css-tricks). In this iteration our check will run only once we’ve stopped scrolling and 250ms have passed since the last check.

For more advanced/robust usage you can use an actual debounce implementation like the one Underscore provides.

Here’s the final outcome (feel free to scroll and click):

light

And that’s it! We’re ready to add a simple back-to-top button to our WordPress (or any kind of) website! Feel free to post in the comments if you decide to add it on your own website or have already done so!

Leave a Reply

Your email address will not be published. Required fields are marked *