DEV Community

Cover image for Making a 'Back to Top' button without Javascript
Jack
Jack

Posted on • Updated on

Making a 'Back to Top' button without Javascript

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. 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), 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.

If you already know about CSS' position property, skip to the code.

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, 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.

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

<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>
Enter fullscreen mode Exit fullscreen mode

The 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' */
}
Enter fullscreen mode Exit fullscreen mode

The JavaScript

¯\_(ツ)_/¯

The final product

basic

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:

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.

Top comments (15)

Collapse
 
viv profile image
Vivek Siva

JS devs be like " where are my animationsssss"

Collapse
 
capsule profile image
Thibaut Allender

You mean html {scroll-behavior: smooth;}?

Collapse
 
jackherizsmith profile image
Jack

Haha! What kind of animations are you thinking about?

Collapse
 
viv profile image
Vivek Siva

all those gimmicy animations, like lets a smooth scrolling to top (like a river :D) or an top arrow that changes color depending on how bottom we are on page etc!

Thread Thread
 
jackherizsmith profile image
Jack

Love the idea of colour changing when scrolling! Or perhaps fading in to full opacity as you get to the bottom...

Collapse
 
rtivital profile image
Vitaly Rtishchev

well, it kind of works but messes up with browser history, user will have to click back button twice which is a bad UX, so just, please, stick to the js solution instead of link

Collapse
 
jackherizsmith profile image
Jack

Hey Vitaly! Thanks for your comment. What browser are you using? href="#" just navigates to the top of page, it doesn't add to the history in the browser which I should have mentioned in the article, I'll update that now. If you have any other reasons to suggest using JS on top of CSS I'd love to hear them.

Collapse
 
capsule profile image
Thibaut Allender

The question is more, what browser doesn't add it to the history? Both the latest Firefox and Chrome add # to the history.

Collapse
 
futureistaken profile image
R Z

Anyway, it's a good idea if you don't want to use onScroll event. You just can add a little bit JS to replace the link with a button.

Collapse
 
rtivital profile image
Vitaly Rtishchev

Yep, that's what I've meant, when replacing js with css, do not forget about the UX

Collapse
 
madmax124 profile image
Syed Saad

Noice

Collapse
 
contradicthelaw profile image
Minh Nguyen (he/him)

I like this! A couple of the websites I help manage has this effect, but I wasn't sure how it was achieved.

Collapse
 
anders profile image
Anders

Very elegant : )

Collapse
 
jackherizsmith profile image
Jack

Very kind thank you!

Collapse
 
whjeon profile image
WooHyung Jeon

Amazing! learned alot!