Web DevelopmentWeb Accessibility in React

a hand pointing to a web accessibility button

Introduction

Web Accessibility is a field of work focused on removing obstacles that often arise when a disabled person interacts with websites and apps. If they are well-designed and coded in line with the principles of semantic HTML and accessibility rules, then we have bigger chance that all users will enjoy equal access to information and functionalities.

How does a disabled person use the web apps?

According to the WHO, around 15% of people all over the world live with some kind of disability. There are four main categories of disabilities, and each of them require specific technologies, tools and programs for the disabled person to be able to take full advantage of the benefits of the Internet.

Categories of disabilities:

Visual disability - sight impairment, short-sightedness, blindness

  • use of screen readers or braille readers to interact with a web page

  • use of zoom on web page display, use of high contrast setting

Motor disability - injuries, RSI, paralysis, movement limitations

  • use of programs and tools scanning eye and head movements for website navigation

  • voice commands

  • switches

  • Switch Access (Android)

Hearing disability - partial or complete hearing loss

  • sharing transcriptions and sound information

Cognitive / intellectual disability - ADHD, dyslexia, autism, and others

  • for instance, people with dyslexia can make use of a browser extension which puts different color gradients on chunks of text to make them easier to read

What is important when writing an accessible app?

It is vital to understand that accessibility is not an optional part of an app, but rather a necessary and inherent one. It is also vital to consider the needs of the end users — the disabled, and how those needs should be met in the process of using the app.

WAI (Web Accessibility Initiative) is an initiative by W3C (World Wide Web Consortium). Its goal is to improve the accessibility of the Internet for the disabled, e.g. by sharing the rules, specifications and guidelines as to what is the process of writing an accessible web page or app. Below are listed some of the selected documents and specifications:

  • WCAG 2.1  — document including the information on how to build an accessible web application for everyone

  • WAI-ARIA — a technical specification describing the set of recommendations on improvements of accessibility within complex web applications

The above-mentioned specifications are vast documents with substantial number of pages, however, comprehensive summaries can be found on the Internet.

Additional perks to writing accessible code:

  • Better sales opportunities with accessible sales apps due to a wider range of potential customers (and higher risk of getting negative feedback with non-accessible solutions).

  • Current EU legislation on accessibility on public institutions’ websites impose a set of requirements that need to be met. Such regulation may expand on private venture in the future and it is best to get ready in advance.

Real-life example of writing an accessible application

First, let’s recap once again what screen readers are and what is their role.

To put it simply, a screen reader is a part of AT (assistive technology) and it is a computer program used for text processing (e.g. on a website). It is also able to read it aloud thanks to speech synthesizer. It is an indispensable tool for the visually disabled.

There is a lot of similar software on the market, JAWS, VoiceOver, Talkback and NVDA, to mention a few.

In our basic application we will use ChromeVox extension to the Chrome browser as our screen reader.

Let’s fix our inaccessible app

What should you pay attention to while writing accessible apps in React?

  1. Some of HTML attributes, like class or forare slightly different in JSX: they are in camel case style and wording is different: className, htmlFor

  2. ARIA attributes in JSX are written in the same manner as in HTML: e.g. aria-label

  3. To set focus on something we can use Refs which gives access to DOM

  4. Of course, React fully supports HTML so using appropriate semantic tags or attributes is highly recommended.

https://www.w3.org/WAI/WCAG21/quickref/#predictable

One of the basic principles of writing an accessible web app is to check the navigation through the website with the Tab key. Navigating should be consistent and logical. Focus on interactive elements like inputs, links, and buttons, should also be visible. Unfortunately, the focus is invisible in our application, because outline is turned off for all inputs and buttons:

input, button {
    outline: none;
}

Let us then delete this property from the source code.

Now, after pressing the Tab key, we can see which input or button is currently active.

Note: We are not forced to using outline property implemented by user-agent. In order to change it, we must set the property to value: outline: none, and additionally define our own styles using a pseudo-class :focus .

Description of the elements included in the form

https://www.w3.org/WAI/WCAG21/quickref/#labels-or-instructions

Inputs, checkboxes, radio buttons and others should be connected with a <label> tag.

In our code, it looks like this:

<label className="label">Name</label>
<input className="input" type="text" />

Let’s take a look at what the Chrome Vox reader tells us. When reaching the first field with the Tab key, the only words we hear is “Text editing” and that does not inform a blind person which field is going to be edited.

It’s a bug resulting from lack of connection between the input and the label. One of the ways to combine those tags together is by adding an htmlFor attribute to <label> and id for <input> the same value.

It will make the tags connect and what we will hear now is “Name, text editing.”.

Additionally, the clickable field for this input has become larger, which helps the users with motor disability, because after clicking on a label, the focus will center on the text input connected to that label.

<label htmlFor="name" className="label">Name</label> <input id="name" className="input" type="text" />

Note: Unfortunately, it often appears that we don’t have a label for editable field on our proposed design. It does not mean that we shouldn’t include it in the code. Is it enough then to set visibility: hidden or display: none for <label> it’s a good direction, but such actions would make <label> invisible also for the screen reader. The best solution is to use a certain trick: to hide it visually, but not for the screen reader.

The style of the hide-element class:

.hide-element {
  border: 0;
  clip: rect(1px, 1px, 1px, 1px);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
}

Note: We add a class with those properties to the label, which allows the screen reader to read the value from the label.

Required fields using aria-required attribute from the ARIA attributes set.

https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA2

ARIA is a technical specification, containing a set of recommendations concerning improvement of accessibility for complex Internet applications. It includes some special accessibility attributes, which can be included in the HTML code.

A text input with required the attribute has been used in the application, which allows the native browser field to launch.

<input id="name" className="input" type="text" required />

The problem is, however, that a blind person can’t know that this field is required. In order for the screen reader to be able to know that, we must add aria-required={true}.

<input ... aria-required={true} />

Accessible modal

https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/dialog.html

After entering values into text fields E-mail and Password, followed by clicking Send button or pressing Enter, the modal appears. How does it look from the accessibility point of view? Let’s check it on our ChromeVox example. Sadly, after clicking Send button, we don’t get any feedback on the modal, we only hear the word “Send”, since the focus remained on this button.

1. Setting the focus on the modal

First, we will need refs to access DOM, or rather, to the node representation of the modal in DOM, and in case it gets opened, we need to set focus and corresponding tab-index on it.

// index.js

childRef = React.createRef(); // create Refs

<Popup ref={this.childRef} // attach created Refs to component

handleSubmit = e => {
    this.childRef.current.focus(); // set focus after click
};

// Popup.js

// use Forwarding Refs
const Popup = React.forwardRef(({ isOpen }, ref) => (
    <div
      ref={ref}
      tabIndex={isOpen ? 0 : -1} // if open then tab-index="0"
    />
);

In this case Refs grants us access to the modal, which in this case is <div> tag, being a building block for the modal. We can set the focus on it using focus() function. However, <div> has no implemented focus by default and the outline won’t show. tabIndex can help us overcome this problem and force it to show. When setting tabIndex={0}, we ensure that the element is taken into account during navigation.

2. Adding role="modal"

<div class="popup" role="dialog">

ARIA makes available a role attribute with various values, which enable the transfer of information on the importance of an HTML tag to the assistive technology. The vast majority of HTML tags already have a native role and a significance. For instance, the <button> tag means a clickable button, and <header> is an introductory content. By adding role="dialog", we tell the screen reader that it’s dealing with a modal.

3. Closing modal button — changing <div> for <button>, adding aria-label and aria-hidden

Visually, the “X” sign gives us a clear hint that it serves for closing the modal. However, the button is entirely inaccessible, because the screen reader has no clue whether it’s actually a button there and what is its purpose.

Errors:

  • a semantically empty <div> tag has been used

  • lack of focus

  • the “X” sign used inside is just a character “X” for the reader

<div className="close-popup" onClick={handleClosePopup}>X</div>

The first two problems can be solved very easily by changing the tag <div> for <button>

<button className="close-popup" onClick={handleClosePopup}>
  X
</button>

The “X” sign problem can be solved by adding to <button> an aria-label attribute with text value what is the function of the button; and at the same time, by enveloping the “X” sign in <span> tag and hiding it for the screen reader with aria-hidden attribute.

4. Exiting modal with Esc key

The function disableListEsc is listener on the whole document and the function listenerOnEscKey lets us check if Esc key has been pressed.

disableListEsc = () => {
    document.addEventListener('keydown', this.listenerOnEscKey);
};

listenerOnEscKey = evt => {
    if (evt.key === "Escape") {
        this.setState({ isOpen: false });
    }
};

The pop-up has been fixed. Now, when clicking the Send button, the voice synthesizer tells us: “You have opened a dialog box, mail has been sent.”. We learn about the modal that’s been created, and at the same time we hear the text content of the modal being read aloud.

5. The result of the improved application

Helpful tools in process of writing accessible applications

During the development phase, it is worth to equip ourselves with modules or extensions, which facilitate writing code according to the website accessibility guidelines.

Comparing the two application versions in Accessibility Audit in Chrome

Before:

After:

Why is the score only 88, and not 100? Because the audit discovered that contrast between background and label text color is too low.

https://www.w3.org/WAI/WCAG21/quickref/?versions=2.0#qr-visual-audio-contrast-contrast

But that’s designer’s job to get the colors right 😉

Note: of course, we could add a contrast-changing feature, but the colors should be set with adjusted contrast by default

Has the app become accessible for every user?

It certainly has become more accessible compared to what was before and has substantially improved in terms of accessibility and usability for the disabled users.

The audit brought up before indicated the accessibility score of 88 out of 100. We would have reached 100/100 after correcting the contrast issue, however, it does not imply that the application is accessible for each and every user in the world. What is important here is the message produced by the audit: “These checks highlight opportunities to improve the accessibility of your web app. Only a subset of accessibility issues can be automatically detected so manual testing is also encouraged.”. What it means, is that a crucial part of testing the application’s accessibility is to run a manual test, preferably carried out by a disabled user.

Additionally, during the improvement of the application, we have adopted blind and short-sighted users’ point of view while using the screen reader. It was a good approach, given such an easy example, yet with more complicated applications, a lot of different requirements need to be met. There are many kinds of disabilities and the WAI rules specify numerous different guidelines, such as sans-serif font (for people with dyslexia), larger clickable area on interactive elements (for people with motor disability), or coherent and predictable application format (for people with autism).

Useful links/bibliography:

Updated at15.01.2024
Published at17.05.2019
Irek Róg
Irek Róg

Frontend & Mobile Tech

Stanislav Naborshchikov
Stanislav Naborshchikov

Solutions Specialist

Table of contents

  1. Introduction
  2. How does a disabled person use the web apps?
  3. What is important when writing an accessible app?
  4. Accessible modal
  5. Helpful tools in process of writing accessible applications
  6. Comparing the two application versions in Accessibility Audit in Chrome
  7. Has the app become accessible for every user?
  8. Useful links/bibliography:

Share the article

Did you like the article?Find out how we can help you.

Matt Sadowski

CEO of Mobile Reality

CEO of Mobile Reality

Related articles

Discover the top 5 Vue tools and libraries for web development in 2024. Elevate your projects with these must-have components! Boost your Vue skills now.

15.11.2024

Discover the Top 5 Vue Libraries in 2025

Discover the top 5 Vue tools and libraries for web development in 2024. Elevate your projects with these must-have components! Boost your Vue skills now.

Read full article

Master the best practices for Node.js app development. Learn expert tips and techniques to elevate your skills.

19.06.2024

Essential Best Practices for Node.js App Development

Master the best practices for Node.js app development. Learn expert tips and techniques to elevate your skills.

Read full article

Discover essential React JS Best Practices for Frontend Development Teams. Elevate your coding game with expert tips and techniques.

22.04.2024

Top ReactJS Best Practices for Frontend Teams

Discover essential React JS Best Practices for Frontend Development Teams. Elevate your coding game with expert tips and techniques.

Read full article