Making React Apps More Accessible

Jess Mitchell

Spending some time making your React app accessible can help ensure a wider range of people can use all the amazing interfaces you’re building. Thankfully, improving how accessible an app is often requires only minor changes to your components.

Quick Intro to Accessibility

Building accessible apps means helping as many people as possible interact with your app’s interface. This includes individuals with auditory, cognitive, neurological, physical, speech, and visual impairments. It can also include temporary conditions, like a broken wrist, that may prevent someone from interacting with an app how they usually would.

"a11y" is a numeronym for "accessibility". It refers to the first and last letters, and the 11 letters in between. 🤓

✨ Black Friday - 50% off all of Wes Bos' courses

Recommended React and GraphQL course

Who is Accessibility for?

The short answer is that accessibility is for everyone! ✨ Accessible apps often have better user experience (UX) because they have more intuitive interactions. High colour contrast, for example, makes reading text easier for everyone–not just someone with a visual impairment.

Accessible apps improve the UX for everyone, not just those who interact with apps differently than the "average user".

Making React Accessible

Thankfully, there’s nothing inherently inaccessible about React. Given that React apps are component-based, though, it can be easy to lose track of how accessible your app is from a broader view.

Let’s look at five specific ways to make React apps more accessible.


1. Structuring Your App with Semantic Markup

Semantic markup is HTML that uses elements titled for their purpose.

Most of us React developers have gotten pretty comfortable with our trusty div elements. Ditching the div and using semantic HTML instead can be incredibly helpful for a couple reasons, though:

  1. Screen readers understand the importance of each element better.
  2. The codebase itself becomes more self-explanatory for developers.

To see why semantic HTML is useful, let’s first look at an unordered list component using only divs:

...
render() {
  return (
    <div>
      <div className='title'>
        Favourite Foods
      </div>
      <div className='list'>
        <div className='item'>
          - Sushi
        </div>
        <div className='item'>
          - Pizza
        </div>
      </div>
    </div>
  )
}

It’s not immediately clear what this component is unless the classes and structure are considered. The screen reader definitely can’t tell what these elements are supposed to be so we can consider this list pretty inaccessible. 🙈

Let’s try this again with semantic HTML now:

...
render() {
  return (
    <section>
      <h2>Favourite Foods</h2>
      <ol>
        <li>Sushi</li>
        <li>Pizza</li>
      </ol>
    </section>
  )
}

As a developer, we can now clearly see what these elements are and the screen reader knows their purpose as well.

As a default, try to use elements other than div in your components. There are often better options that can greatly improve accessibility and readability (like header, footer, section, aside, etc. ✨)

2. Upgrade Semantic Markup with ARIA Attributes

ARIA stands for Accessible Rich Internet Applications. ARIA attributes aren't required and can instead be considered a supplement to help the HTML be read by a variety of devices.

As we’ve seen above, semantic markup makes your codebase more readable for screen readers. We can get even more specific now with ARIA attributes.

Let’s say we get instructions to add a button that increments something. One option would be to make a div and add an onClick event to it like so:

...
render() {
  return {
    <div>
      <div>Increment Something</div>
      <div onClick={this.incrementSomething}>
        +
      </div>
    <div/>
  )
}

Unfortunately, the screen readers won’t know this component is a button or that the label is related to it.

Now let’s look at a more accessible version:

...
render() {
  return (
    <button
      onClick={this.incrementSomething}
      aria-label='Increment Something'>
      +
    </button>
  )
}

Compared to the first example, the screen reader now knows it’s a button because we’re using a native HTML button. It can also tell the user what the button does from the aria-label. 💪

Now let’s say you can’t convert your component to a button for some reason or you want to keep the label in the user interface (UI). No problem. We can use the role and aria-labelledby attributes to keep the the screen reader in the loop.

...
render() {
  return (
    <>
      <h3 id='incrementButtonTitle>
        Increment Something
      </h3>
      <div
        onClick={this.incrementSomething}
        role='button'
        aria-labelledby='incrementButtonTitle'>
        +
      </div>
    </>
  )
}

The role prop tells the screen reader the element should be read as a native HTML button, and the aria-labelledby attribute says the element with that ID (the <h3>) is the button’s label. 🎉


3. Using an Element’s Focused Styling

The browser’s default focus styling isn’t the prettiest styling you’ll see but it’s incredibly helpful for navigating apps with your keyboard.

To see the your browser's focused styling, try hitting Tab a few times now and you should see a border around the currently focused element.

After tabbing a few times, imagine that border was not around that link in the nav bar and you couldn’t use your mouse. When there are no visual indicators of what is currently focused, it’s nearly impossible to select the intended element.

The easiest solution is to always leave the browser’s default focus styling. Alternatively, if the default styling doesn’t fit your designs, override the default styling with custom styling like this:

a.nav-links:focus {
  outline: 0;
  border-bottom: 2px solid pink;
}

In general, the web is inherently accessible. Design decisions, like removing focus styling, can reduce a website's accessibility. That means a lot of the work is already done for you if you leave those default styles! 🌈


4. Tabbing Right to the Important Parts

Letting people navigate your app using just their keyboard is a great way to improve accessibility.

One way of doing this is to take advantage of the tabindex attribute. It allows the developer to control the order of elements focused while tabbing outside of the default order.

Only elements that can be interacted with (like an input) are included in the tab order.

By default, the tab order is the order of elements as they appear in the DOM.

...
render() {
  return (
    <footer>
      <a href='#link1' tabindex='3'>
        first
      </a>
      <a href='#link2' tabindex='2'>
        second
      </a>
      <a href='#link3' tabindex='1'>
        third
      </a>
    </footer>
  )
}

In this case, instead of tabbing through the links in the order they appear (first, second, third), the tabindex controls the order (third, second, first).

There are a few ways to change the default tab order:

  • Positive Numbers: The tabindex is read sequentially, with tabindex='1' being the first to received focus (then 2, 3, 100, etc.).
  • Negative Numbers: Using a negative number will prevent an element from being accessible from the keyboard (e.g. tabindex='-3') but is uncommon for improving accessibility.
  • Zero: A tabindex of zero/0 will allow a user to tab to an element that can’t be tabbed to otherwise. This can be useful if you’re unable to use semantic HTML.

Always test the UX of adding a tabindex to your React components to make sure it helps users more than it hinders them. If your HTML is semantic, you shouldn't need tabindex.


5. Alt Text on Images

The alt (or “alternate”) attribute is another quick way of making your React app more accessible. When a screen reader reaches an image, it will read out loud the alt text to provide a description of the image’s content.

const AlligatorImg = () => (
  <img
    src='./img/alligator.png'
    alt='Alligator coming out of water with mouth open'
  />
)

The purpose of the alt text is for the person hearing it to understand the content of the image. It should be specific enough that the person can imagine the image without seeing it.

Your alt text doesn't need to include phrases like "Picture of" or "Image of". The screen reader already knows it's a picture because it's an image element, so there's no need to add that! 🤓

As a general rule, try to keep your alt text concise (about 20-100 characters) but still descriptive. Being too concise (like alt='alligator') won’t tell your user very much about the photo.


Further Reading

Overall, accessibility is a big topic and there are many ways to maximize how many people can use all your amazing React apps.

If you’d like to do a deeper dive, check out the WAI (Web Accessibility Initiative) for more tips.

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#