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

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.


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 best part of this approach? It requires no focus management! 🎉

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!

The React Code

As you may have read in my post about Skip Navigation Links, I use Next.js 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:

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

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)
  2. The value of the setting is no-preference (which unfortunately is the default value)
html {
  @media (prefers-reduced-motion: no-preference) {
    scroll-behavior: smooth;
  }
}
Enter fullscreen mode Exit fullscreen mode

One thing to keep in mind is that scroll-behavior does not have full browser support. 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!

Top comments (6)

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)

Nice catch! Will update soon.

Collapse
 
phongduong profile image
Phong Duong

Great tip. Thank you for sharing

Collapse
 
ashleemboyer profile image
Ashlee (she/her)

Thank you!

Some comments may only be visible to logged-in visitors. Sign in to view all comments.