Skip to content
Slide 1 screenshot
Slide 1

React and Accessibility

Event
React Zurich Meetup
Date
Hosted by
ti&m AG
Slides
Download Slides (1.4MB PDF)

Why should we care about accessibility (A11Y)?

I used to think of accessibility as developing websites for blind people. I couldn't be more wrong.

Accessibility impacts more people than we think. There are around 1.3 billion people with disabilities in the world. The equivalent to the whole chinese market.

There are several types of barrier that impact users on the web:

  • auditory disabilities
  • cognitive disabilities
  • physical disabilities
  • speech disabilities
  • visual disabilities
  • Aging

Additionally, some people might be experiencing temporary impairments that may occur due to an accident, surgery, or medication.

Another good reason to invest in accessibility is compliance or certification.

Most countries already require some sort of accessibility compliance with WCGA 2.0, or Section 508, or ADA. In some countries, regulation also forces private companies to adhere to accessibility standards, such as Norway.

Now is a good time for you to start investing in accessibility.

Building more accessible web applications and websites is easier than you think.

Web technologies are getting more accessible, and there are a ton of accessibility tools that developers can use. It has never been easier to start.

However, most websites have accessibility errors.

(2 slides were omitted from original talk)

The WebAIM Million evaluated the top 1 million homepages using automated testing tools.

Automated accessibility testing is not perfect. In fact, it only catches around 30% of all accessibility errors (you should always perform manual tests  your website).

But even so, the study found that almost 98% of websites had accessibility issues.

Websites using React had, on average, 10% more accessibility problems.

We are preventing people from using our websites by making them inaccessible.

We need to do better as web developers. We need to create more inclusive websites because this part is of our job.

We will see some accessibility tips and best practices in React. However, most of this accessibility guidelines applies to other frontend frameworks. This is not meant to be a React vs Vue vs Angular type of argument.

It contains structural patterns, interaction patterns and application patterns.

Accessible Structural Patterns

HTML5 Landmarks

People without any visual disability are used to open a website and see all the content at a glance. We can see the header, navigation links, and we can already see where and what the main content of the page is. We immediately know what the page is all about.

People who navigate the internet using screen reader software have a completely different experience.

Learn how to test your website with a screen reader.

(7 slides were omitted from original talk)

There are several types of landmarks, and they usually have HTML5 equivalent tags.

For example, if you use the header HTML5 tag, and it is not within any article, aside, main, or section, it will be inferred as having the header role by screen readers.

The main tag, which you should only have one per page, will also be automatically inferred as the main landmark.

The footer tag will also be inferred as the contentinfo landmark if not present within any article, aside, main, or section tag.

The nav tag will be automatically inferred as the navigation landmark.

The section tag will be automatically inferred as the region landmark.

To provide more information to screen reader users you should label your section landmarks.

The form tag will be automatically inferred as the form landmark.

The aside tag will be automatically inferred as the complementary landmark.

There is one more landmark type, the search landmark, that has no HTML5 equivalent.

Let's see how can we use landmarks to create more accessible websites.

In this example, the header, main, and footer elements are automatically assigned their landmark roles.

We can then override when needed. In this case, there is a search form on the page. We can enhance this form by passing the attribute role="search", making this a search landmark.

Because we have multiple nav elements on the page, we can label each one using the attribute aria-label="primary" and aria-label="secondary" correspondently.

It&s redundant to write aria-label="primary navigation" as screen-readers already know that the landmark is of type navigation. Otherwise, the screen-reader announces it as “primary navigation navigation”, which is quite annoying.

We should also make use of the aria-label attribute in the search input field. Visually, our design is enough to convey the meaning of the form, but screen reader users will have no information for this field.

Similarly, we can make use of the attribute aria-labelledby and reference an ID of another element in the page. This element acts as a label of the section.

Forms Accessibility

Everyone hates forms. The experience for screen reader users is even worst.

Here are 3 tips to make forms accessible.

(1 slide was omitted from original talk)

Accessibility Tip #1

Always label your input elements.

The easiest way to do this, is to surround your input element with a label, and add the labelling text as a sibling of the input.

Another way to label input elements, is to make use of the htmlFor attribute (in JSX, the html attribute for is used as htmlFor).

The value of this attribute needs to be a valid ID pointing to an input element with that ID.

But careful with this approach in React. If you are writing a component, you don't know where and when it is going to be used. You can't assume that it will only be used once on the page.

If you are using the component, be sure to make this IDs unique. I recommend you use the first approach, as to avoid this issue altogether.

Labelling an input is extremely important. Even if your designer didn't visually put a label there.

I'm talking about input fields that visually look like their label is the placeholder.

Screen readers don't consider the placeholder attribute as a label, and it won't be announced. Nonetheless, many of those input elements on the are implemented like this.

To make this input accessible in React you can make use of a nice <VisuallyHidden /> component.

With only a few lines of CSS, we can hide the element in the screen but still make it announced by screen readers.

You can use it as you would use a label element, except, nothing will be displayed on the website.

Accessibility Tip #2

Another way to label your inputs (or anything else) is to use aria-label or aria-labelledby attributes.

Icons accessibility

Another common element on websites, are icon links or icon buttons icon. In this example, with an arrow icon.

The icon in this scenario is only used as a decorative element, and it doesn't constitute any type of textual meaning we want our screen-reader users to be read.

We can make use of an aria-hidden="true" attribute, to hide the element from the accessibility tree. This makes screen-readers not announce the element for our users.

A similar example is when we have links that are only made out of icons. For example, we often see social links in the footer of websites, where the logo of these social networks is used for the link itself.

And while this is effective for people without visual disabilities, people who can't see the icon have no idea where the links points to.

We can make accessible icon buttons in two steps:

  • hide the link from the accessibility tree, by using aria-hidden="true" on the element with the image, usually an svg.
  • provide a text alternative to the link, by using the aria-label attribute on the link it-self.

(1 slide was omitted from original talk)

Accessible Interaction Patterns

Form Validation

These examples make use of Formik, a React package that makes form validation a lot easier.

One error that we sometimes do is how to associate form errors with their inputs.

The right way to do it is to use the attribute aria-describedby, with the value being the id of the error element associated with the input.

One note, make sure the IDs are unique within a page.

There are two ways we can improve form validations.

The first is to provide live form validation, as the user types. For screen-reader users, this means adding the attribute aria-live="polite" to the error element.

When text changes inside this element, the screen reader will announce it.

However, for some types of fields, we don't want the errors to be shown or announced as the user types.

Take the example of an email field. When the user starts typing, the field is invalid. It will only become a valid email, when the user is very close to finishing typing the email address. We don't want the error to appear visually as the user types, or being announced by our screen readers.

To change this behavior, we can change the aria-live attribute to assertive. This causes screen readers to only announce the error when the user leaves the field by “un-focusing” it.

Icon Toggle Buttons

They are used as “on/off” switches. Spotify uses this in multiple places throughout their web application, including to “mute/un-mute” the sound.

(1 slide was omitted from original talk)

Let's consider a button responsible for “muting/un-muting” the sound. Visually, the button is only shown with two icons, one when it's active (sound is on) and one when it's inactive (sound is off).

The first thing we need to do, is to provide a text alternative for the button. We can do that by adding the aria-label="Mute" attribute.

The second thing we need to do, is to mark the icon as purely decorative, by adding an aria-hidden="true" attribute.

And finally, we need to make this button behave like a toggle and not a button. The difference between them is that the toggle has an internal state (signalled visually as an icon change) that makes the button active/inactive.

We can provide this state to screen reader users by adding an aria-pressed="true" or aria-pressed="false".

As we're creating an icon button in React, we can abstract this in a prop of type boolean (yay, React!).

Accessible Application Patterns

Accessible React Router

Most React applications have routing, such as the popular library React Router, which has a few accessibility issues.

When a user navigates to a new page, nothing is announced by screen reader users. It's like nothing even happened.

We can fix the react router problem with focus management.

When we change to a new page, we need to change the focus to the new component that was just mounted.

There are a few things that we need to do to achieve this in React.

First, we need to add a tabIndex={-1}, in order to make the container of the new page “focusable” (it will likely be a “non-focusable” element such as a section).

We should also make sure that this element is properly labelled. As the new page will likely have an h1 element, we can use this element to label the container by adding id="title" attribute to the heading and a aria-labelledby="title".

Lastly, we need to move the focus to this container element (now a “focusable” element).

To achieve this in React, we first need to create a variable containing a ref to the element.

And finally, once we have a ref to the element, we can focus the element once the component mounts.

This example uses React Hooks to focus an element by calling ref.current.focus() inside a useEffectcallback.

If you're not using hooks, you can achieve the same by calling this inside a componentDidMount.

Accessible Notifications

Web applications need to notify the user something has happened. Consider an e-commerce website, we need to notify the user once an item has been added to the cart.

We would have a cart icon with a number of items in it displayed. No problem with this for people with no visual disabilities, as they can not only see the total number of items in the cart at a glance, but also see when a new item is added.

To make this pattern accessible for people using a screen reader, we can start by making use of the <VisuallyHidden /> component to provide a text alternative to this information.

We can then add two html attributes: role=status – to signal that this component will have live messages being announced – and aria-live="polite" – so that when new content is added inside of it, it's immediately announced without user interaction.

Another similar pattern, is when we have global flash messages being shown the user. This messages would be shown as soon as something relevant happens like updating data on a user profile, internet connection being lost, etc.

Let's assume we have a component called <Announcements /> that receives a prop announcements: string[]. This component is responsible for showing incoming messages. We can imagine this component being used once as part of the application layout.

In this example, each message is preceded by an icon showing if it's a success, warning, or error message (note that is good to have an icon and not only a color, as we should never rely on color alone as some people might suffer from color blindness).

To convey the same meaning of the icon for people using a screen reader, we need to first add an aria-hidden="true" to the image html element.

And also provide a text alternative for the icon meaning, using the <VisuallyHidden /> component.

Lastly, as new announcements will be shown over time, we need to add an aria-atomic="true" attribute, which makes screen readers only announce newly added content.

Our mission is to make
the web more accessible

This is the right thing to do. Our goal is to enable you to create accessible products by building meaningful tools, raising awareness, and increasing your teams's expertise.

This will make accessibility time and cost efficient.

We also provide on-site training and extensive accessibility audits.
We'd love to work with you.

Liliana Medeiros Guerra

Liliana

Founder

liliana@aditus.io
João

João

Founder

joao@aditus.io

Be the first to know when we're ready

We're building the next-generation accessibility tool, and this can't be done without you. We're looking for accessibility superheroes.

To be notified when we launch, drop your email below.

Leave your email and we'll get in touch when we launch. You won't get SPAMed.