Skip to main content

Joel M. Turner

Beginning Web Accessibility in React

I recently decided to dive into learning accessibility on the web. So many of the great developers that I follow on Twitter advocate for accessibility and I figured it was time to see what it would take. So far, I love it.

If you’re interested in web accessibility I would suggest Gatsby, which gives a lot of win out of the gate and @MarcySutton who is an accessibility advocate and has a package, no-mouse-days that can disable the cursor on your site or app for a day. Nothing helps me see the cracks like taking away my comfort zone. Time to grow!

There are a lot of resources online to help us learn so there’s nothing new in this post. I just wanted to document what I have found and learned so far.

Linting Rules for a11y

One of the best ways to get some useful suggestions is to add the plugin, eslint-plugin-jsx-a11y to your project. After I got it installed my editor lit up like New York City at night. Whew, I had some work to do.

WAI-ARIA

WAI-ARIA is explained well from MDN:

WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) is a specification written by the W3C, defining a set of additional HTML attributes that can be applied to elements to provide additional semantics and improve accessibility wherever it is lacking.

The three main features are Roles, Properties, and States.

Roles

It’s best to use semantic elements for desired actions. A good example is to use the button element for a user action. If we are using a different element to perform the role of a button we can use a role to help out. An example might be an svg icon with an onClick method.

1<svg viewBox="0 0 128 128" onClick="{myOnClickFn}" role="button">
2 <path d="M 10 10 H 90 V 90 H 10 L 10 10" />
3</svg>

Having a role of button tells the screen reader that the intention of this icon is to be a button.

Here’s a list from MDN of all the ARIA roles.

Properties

Properties let us give an element extra meaning if needed. A common example is in a form input. We may have a visual indicator to show that an input is required. Now we can add a data attribute of aria-required="true" to let the user know that the input needs to be valid.

1<form onSubmit="{onSubmit}">
2 <label for="fieldName">Name</label>
3 <input name="fieldName" type="text" />
4
5 <label for="fieldEmail">Email</label>
6 <input name="fieldEmail" type="email" aria-required="true" />
7</form>

States

This is much like states in javascript. We may have a disabled input that will become enabled after validation of a previous field. We can specify the disabled state with aria-disabled="true".

1<form onSubmit="{onSubmit}">
2 <label for="fieldName">Name</label>
3 <input name="fieldName" type="text" />
4
5 <label for="fieldEmail">Email</label>
6 <input name="fieldEmail" type="email" aria-required="true" />
7
8 <label for="fieldSubscribe">Subscribe</label>
9 <input name="fieldSubscribe" type="checkbox" checked="false" aria-disabled="true" />
10</form>

tabIndex

This is one that I vaguely knew about. It turns out that there are three types of values that it can take.

  • tabindex="-1" negative one or less allows elements to get the focus programmatically instead of through sequential keyboard navigation
  • tabindex="0" zero allows non tabbable elements to become tabbable in sequential order by adding focus to them in the document’s source order
  • tabindex="1" one or more makes the elements tabbable in the specific index order represented by this number

onKeypress handler

For all the user clickable elements we can also provide an onKeyPress that handles an Enter or Return key on a clickable element. We can use a function to check for that keypress and if it’s is the key we’re looking for we can pass the event to the onClick function.

Here’s a great snippet from John Luke Garofalo’s post about React accessibility:

1// attach to a onKeyPress to handle Enter keyboard
2// presses in the same way as onClicks
3export const handleEnterKeyPress = onClick => event => {
4 if (event.key === "Enter") {
5 onClick(event)
6 }
7}

Here’s that snippet in TypeScript:

1type HandleKeyPress = (
2 onClick: React.EventHandler<React.MouseEvent | React.KeyboardEvent>
3) => React.KeyboardEventHandler<HTMLElement | SVGElement>
4
5// attach to a onKeyPress to handle Enter keyboard clicks in the same way as onClicks
6export const handleEnterKeyPress: HandleKeyPress = onClick => event => {
7 if (event.key === "Enter") {
8 onClick(event)
9 }
10}

Conclusion

Hopefully this helps you dip your toes into the accessibility pond. I have a lot more to learn and implement but I feel like this was a good start. I would love to hear your resources if you have started down this road as well.

Discuss this article on Twitter