Making a 'Back to Top' button without Javascript
Tags: css, html, tutorial, codenewbie
Published: 2020-10-11 12:27:31

# The 'back to top' button

Here is my tutorial on making a 'back to top' button without JavaScript. Please also refer to [these very helpful design guidelines](https://www.nngroup.com/articles/back-to-top/). Do let me know in the comments if there is anything here I can be doing differently, especially if I've missed anything regarding accessibility.

## Why?

I recently built a portfolio site for a freelance journalist who required a lightweight portfolio site (which I did with [Eleventy](https://www.11ty.dev/)), where she could host her articles and have visitors contact her.

When I got to designing the full-length article page itself, I wanted to provide a button for readers to get back to the top since there is information that could be of interest after reading: a link to download the original article as a PDF, another to the online article, details like when it was written and so on.

## How to implement it?

I asked Google how this could be done - I find it helpful to get different perspectives on solutions before diving into code. I was surprised to find that every answer involved using JavaScript / jQuery. Unless I'm missing something, most code concerning layout that _can_ be done with CSS, should be. JavaScript breaks more easily, requires more work by the browser and [not all users run JavaScript](https://www.wired.com/2015/11/i-turned-off-javascript-for-a-whole-week-and-it-was-glorious/).

{% twitter 1303268890638778368 %}

If you already know about CSS' `position` property, [skip to the code](#putting-it-all-together).

## Getting into `position`

We need to understand the various CSS positions:
- `static`: this is the default value for every element and is named only so that it can be referred to when describing what other positions do. A more helpful name might be `none`. The only time you would ever need to use it would be to remove an element's `position` that had been set elsewhere in a less specific [declaration block](https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax#CSS_declaration_blocks), i.e. you never need to use it (just go and remove the `position` property from that other block). Think of `static` as 'unpositioned', in that it just happens to be where it ends up on the page. This is very useful, because you want most of your elements to 'end up' where you'd expect... it's just that you don't need to apply this property in order for that to happen. As far as I know, this is the most anyone has ever written about the `static` position.
- `relative`: this establishes the element on the page, _relative_ to where you'd expect it to be (its `static` position). If you add `left: 20px;` it will move 20px from the left edge of where you'd expect it to be. If you make an element `relative` without also changing its position, it might look like nothing has happened but your CSS now knows it is there on purpose (unlike an 'unpositioned' `static` element), and so it can now be used as a reference for any child elements.
- `absolute`: an `absolute` positioned element will go anywhere on the page relative to its closest parent that isn't `static`, or `body` if it doesn't have one. With `top: 0;` this will line up the top of the `absolute` element with the top of its closest positioned parent.
- `fixed`: sets the position of an element relative to the window rather than anything on the page - the Dev.to navbar that you can see at the top is `fixed`, for example, so it scrolls _with your screen_ not with the page (unless you've changed this default in your settings).
- `sticky`: this toggles between `relative` and `fixed`. It will behave like a `relative` element until it gets to its `sticky` position, and stays `fixed` there until its containing element no longer accommodates its position and it toggles back again. This CSS `position` has been around since 2013 and is up to 95% global usage when using the -webkit- prefix according to [caniuse](https://caniuse.com/?search=sticky).

## Putting it all together

So, we're going to make a `relative` page (`<main>`) with an `absolute` scrollbar (`<div>`) that contains a `sticky` button (er, the 'button' is in fact an anchor element, since it navigates rather than triggering an event.. so let's call it a link from now on: `<a>`).

We won't want to navigate 'back to top' whilst we're already there, so the scrollbar should begin below where the screen loads, i.e. at least 100% of the viewport height from the top of `main`. Once we do see the link, we want it to stay in the bottom right, because that's where users expect to find it. Let's say there's a `<footer>` at the end of the page, and we want to prevent the link scrolling to the bottom of `<main>`, so the scroll bar will also be offset from the bottom.

Here is the most basic implementation of the 'back to top' link without using any JavaScript:

### The HTML

```html
<body>
  <main>
    <section>Words</section> <!--your page content-->
    <div class="scroll-top"> <!--scrollbar at the end of main-->
      <a class="scroll-top__link" href="#">Back to top</a> <!--href="#" navigates to the top of the page-->
    </div>
  </main>
  <footer>Footer</footer>
</body>
```

### The CSS

```css
main {position: relative;} /* to place scrollbar */
section {height: 300vh;} /* so we can scroll */
footer {height: 5rem;} /* a typical footer height */

.scroll-top {
  position: absolute; /* relative to its positioned <main> parent */
  top: 120vh; /* starts below the bottom of the screen */
  bottom: 3rem; /* stops scrolling before the end */
  right: 2rem; /* offset from right hand side */
}

.scroll-top__link {
  position: -webkit-sticky; /* for Safari */
  position: sticky; /* 'relative' until element reaches... */
  top: 90vh; /* 90% viewport height from the top, when it becomes 'fixed' - until its container toggles it back to 'relative' */
}
```

### The JavaScript

¯\\\_(ツ)\_/¯

## The final product

![basic](https://dev-to-uploads.s3.amazonaws.com/i/1rrsiqwgd9esolcwvbkq.gif)

I included an outline on all the elements so you can see how `position` is coming into play.

Let's add lots of text to our `<section>` so we don't have to give it an arbitrary height, and introduce smooth scrolling, colour, hover opacity and some padding in our CSS. Here's what that looks like in practice:

{% codepen https://codepen.io/jackherizsmith/pen/oNxVWrK %}

So there it is, all you need to make a 'back to top' link without any JavaScript.

**edit**: `href="#"` in an anchor tag tells the browser to scroll to the top of the page without adding to the history, so this shouldn't affect user navigation.

**much later edit**: the `div` / invisible scroll bar obviously sits on top of the page, so anything underneath it is unclickable. This is a problem for links in text underneath the path of the button.