Accessible, Smooth Scroll-to-top Buttons with Little Code
Tags: a11y, css, javascript, webdev
Published: 2020-11-26 23:52:29

---
title: Accessible, Smooth Scroll-to-top Buttons with Little Code
published: true
description: Adding a scroll to top button with smooth scrolling is as easy as adding a few lines of code.
tags: a11y, css, javascript, webdev
canonical_url: https://ashleemboyer.com/blog/accessible-smooth-scroll-to-top-buttons-with-little-code
cover_image: https://res.cloudinary.com/ashleemboyer/image/upload/v1644169246/social-images/AccessibleSmoothScrollToTopButtonsWithLittleCode_cf49y4.png
---

Some of the original content in this post has been archived. This post previously showed how to create this component with a button element. I've since learned a better approach is to create this component with an anchor element and have it link to a Skip Navigation Link. [You can read the archived post if you want to](https://ashleemboyer.com/blog/archive/accessible-smooth-scroll-to-top-buttons-with-little-code--archived).

---

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](https://www.w3.org/TR/wai-aria-practices-1.1), 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](https://ashleemboyer.com/blog/my-favorite-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 best part of this approach? It requires no focus management! <span aria-hidden>🎉</span>

## Prerequisites

If you don't already have one, you need to add a Skip Navigation Link to your site. It's a quick, easy win as well, and the instructions below reference the one I use on my site. Not sure how to do it? Then read my post on [How I Added a Skip Navigation Link to My Next.js Site](https://ashleemboyer.com/blog/how-i-added-a-skip-navigation-link-to-my-next-js-site)!

## The React Code

As you may have read in [my post about Skip Navigation Links](https://ashleemboyer.com/blog/how-i-added-a-skip-navigation-link-to-my-next-js-site#what-does-the-code-look-like), I use [Next.js Per-Page Layouts](https://nextjs.org/docs/basic-features/layouts#per-page-layouts) to help me render repeated content, such as navigation links, on many pages. The layout I use for the navigation header is where I placed a Skip Navigation Link and Scroll-to-Top link. The code looks something like this:

```tsx
import styles from './base-layout.module.css';

const BaseLayout = ({ children }) => {
  return (
    <div>
      <a href="#main-content" id="skip-navigation-link">
        Skip Navigation
      </a>
      <SiteHeader />
      <main id="main-content" tabIndex={-1}>
        {children}
      </main>
      <a href="#skip-navigation-link">Back to Top</a>
      <SiteFooter />
    </div>
  );
};
```

What's important from this code:

1. The Scroll-to-Top link goes to the first focusable control on the page, which should be a Skip Navigation Link.
2. The `href` of the Scroll-top-Top link matches the `id` of the Skip Navigation Link.

## The SCSS Code

The code below takes an accessibility- and browser-support- first approach. Rather than making the default behavior for scrolling be smooth, an animation which can be physically harmful to some folks (including myself), it only applies smooth scrolling when two conditions are true:

1. The `prefers-reduced-motion` query is supported ([see the CanIUse.com page](https://caniuse.com/mdn-css_at-rules_media_prefers-reduced-motion))
2. The value of the setting is `no-preference` (which unfortunately is the default value)

```scss
html {
  @media (prefers-reduced-motion: no-preference) {
    scroll-behavior: smooth;
  }
}
```

One thing to keep in mind is that [`scroll-behavior` does not have full browser support](https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior#browser_compatibility). At the time of writing, the feature is still in development for Safari.

## 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!