Beginning Web Accessibility in React
Joel Turner
Posted on January 29, 2020
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.
<svg viewBox="0 0 128 128" onClick="{myOnClickFn}" role="button">
<path d="M 10 10 H 90 V 90 H 10 L 10 10" />
</svg>
Having the 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.
<form onSubmit="{onSubmit}">
<label for="fieldName">Name</label>
<input name="fieldName" type="text" />
<label for="fieldEmail">Email</label>
<input name="fieldEmail" type="email" aria-required="true" />
</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"
.
<form onSubmit="{onSubmit}">
<label for="fieldName">Name\</label>
<input name="fieldName" type="text" />
<label for="fieldEmail">Email</label>
<input name="fieldEmail" type="email" aria-required="true" />
<label for="fieldSubscribe">Subscribe</label>
<input name="fieldSubscribe" type="checkbox" checked="false" aria-disabled="true" />
</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:
Make React Navigation Accessible Again
John Luke Garofalo ・ Aug 11 '17
// attach to an onKeyPress to handle Enter keyboard
// presses in the same way as onClick
export const handleEnterKeyPress = onClick => event => {
if (event.key === "Enter") {
onClick(event)
}
}
Here’s that snippet in TypeScript:
type HandleKeyPress = (
onClick: React.EventHandler<React.MouseEvent | React.KeyboardEvent>
) => React.KeyboardEventHandler<HTMLElement | SVGElement>
// attach to an onKeyPress to handle Enter keyboard clicks in the same way as onClick
export const handleEnterKeyPress: HandleKeyPress = onClick => event => {
if (event.key === "Enter") {
onClick(event)
}
}
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.
Posted on January 29, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.