DEV Community

Cover image for Accessible, Smooth Scroll-to-top Buttons with Little Code
Ashlee (she/her)
Ashlee (she/her)

Posted on • Updated on • Originally published at ashleemboyer.com

Accessible, Smooth Scroll-to-top Buttons with Little Code

Scroll-to-top buttons are great for pages that are long enough to require a few scrolls to read everything. They're even better for extremely long pages. Scrolling is a lot of work for some users, especially on a mobile device. We (website creators) can greatly reduce the amount of work it takes to scroll our pages with surprisingly little effort on our part.

One example is the WAI-ARIA Authoring Practices, which is 140,923 pixels tall at the time of this writing. I'm not calling them out, it's just one of my favorite pages on the entire internet! It's a great resource for making accessible custom components.

Making a scroll-to-top button and making it scroll smoothly is probably a lot easier than you think. It's definitely a lot easier than I thought! The code bits I'm about to show are for React and SCSS, but you don't need to know either. The basic concepts here are for JavaScript and CSS. We'll also cover how to get rid of the smooth scrolling when it's an accessibility concern.

The SCSS Code

First, let's make sure this scroll will happen smoothly. To do so, set scroll-behavior to smooth in a global stylesheet under the html element. The media query I've added is for accessibility. Animations can be distracting or for some users, like myself, have vestibular disorders where animations can cause harmful physical effects. These effects can include dizziness, nausea, and headaches or migraines.

We can prevent this harm to these users who have set up their device to reduce motion by using the prefers-reduced-motion CSS media query. Inside of it, we set the scroll-behavior to auto, which is the default. If you'd like to read more about this technique, it's thoroughly covered in WCAG 2.1.

html {
  scroll-behavior: smooth;

  @media (prefers-reduced-motion: reduce) {
    scroll-behavior: auto;
  }
}
Enter fullscreen mode Exit fullscreen mode

The React Code

Now, add a button to the bottom of your page with lots of content. The important line of code here is window.scrollTo(0, 0). This is what will scroll your page to the top. You can read more about this function on MDN.

<button
  onClick={() => {
    window.scrollTo(0, 0);
  }}
>
  Scroll to top
</button>
Enter fullscreen mode Exit fullscreen mode

Managing focus

Finally, we must also address focus management when adding a scroll-to-top button to our sites. If we add nothing else to our code from above, the button will still have focus after it is clicked. What this means for users who navigate pages with a keyboard is that the page's focus is not where they expect it to be. They expect it to be at the top of the page when it's not.

In your button's onClick listener, after window.scrollTo(0, 0), you need to manually put something at the top of your page in focus. In this article, for example, I can call focus on the <h1> element containing the article title. We just need to add one thing to that element in order for this to work without interrupting normal keyboard navigation. That thing is tabindex="-1".

My <h1> element will then look like this (in React):

<h1 id="article-title" tabIndex="-1">
  Accessible, Smooth Scroll-to-top Buttons with Little Code
</h1>
Enter fullscreen mode Exit fullscreen mode

And here's what button will look like with this specific example:

<button
  onClick={() => {
    window.scrollTo(0, 0);

    // focus management
    const title = document.getElementById('article-title');
    title.focus();
  }}
>
  Scroll to top
</button>
Enter fullscreen mode Exit fullscreen mode

Conclusion

That's it! It really is just a few lines of code. After you add this, everyone will be able to quickly scroll to the top of your website. You've also made it so your site doesn't accidentally harm someone who can't tolerate animations! Well done. I am proud of you!


Did you know I have a newsletter? 📬

If you want to get notified when I publish new blog posts or make major project announcements, head over to https://ashleemboyer.com/newsletter.

Discussion (8)

Collapse
smalluban profile image
Dominik Lubański

As it may sound excellent, the scroll-behavior is not supported in any Safari version, so it might be a good idea to point out that in the article. It's a major browser for the mobile web now (I don't say that I like that fact :) ).

Source: caniuse.com/?search=scroll-behavior

Collapse
jgagne profile image
Justin Gagne

Excellent and thoughtful article. (Consider updating the value smoothly to smooth in The SCSS Code section.)

Collapse
ashleemboyer profile image
Ashlee (she/her) Author

Nice catch! Will update soon.

Collapse
arthureichelberger profile image
Arthur EICHELBERGER

Hello Ashlee! 👋🏻

This is some great content, and this is even greater to think about accessibility!

Good luck on your journey!

Collapse
ashleemboyer profile image
Ashlee (she/her) Author

Thank you!

Collapse
phongduong profile image
Phong Duong

Great tip. Thank you for sharing

Collapse
dorothydzavala profile image
Dorothydzavala

I am searching for something easier to learn CSS Concept with your help I got my concept crystal clear