How to be an a11y - Creating Accessible React Apps

By Neha Nivedita

What is accessibility

  • Everyone can access services or products equally
  • Usability regardless of disability
  • Commonly abbreviated as "a11y" or "AX"

ARIA: accessible rich internet applications

ARIA is a set of special accessibility attributes which can be added to any markup, but is especially suited to HTML.

<button aria-label="Close Window">
    X
</button>

<a href="/card-design-woes"
   aria-describedby="desc-card-design-woes"
>
    Card design woes
</a>

<span class="cta" aria-hidden="true">
    I am hidden from screen readers
</span>

Why should you care?

  • 15% of population has some form of disability - that's 1 billion people
  • 8% of population has some form of colorblindness
  • AX isn't a feature, its a necessity
  • Ignoring AX is akin to discrimination

Sources of a11y issues 

  • Devs often write non-semantic HTML
  • Screen readers cannot parse the content meaningfully
  • Apps become inaccessible
<div
  onClick={this.onClick}
  className={looklikeAButton}
>
  Click Me
</div>

Making React apps accessible

Low hanging fruit

  • Supports aria natively
  • Get low hanging fruit out of the way first
    • Use alt attributes
    • Use semantic elements
<img
  src="woman.jpg"
  alt="Woman carrying an umbrella"
/>

<button class="btn">
  Hey, I'm actually a button!
</button>

Update page titles

Page title is the thing screen readers usually read out loud

componentDidMount() {
  document.title = 'Page title';
}
import React from 'react';
import { Helmet } from 'react-helmet';

const PageMeta = (props) => (
 <Helmet>
  <title>Eric's Website: {props.pageTitle}</title>
  <meta
   name="og_title"
   property="og:title"
   content={props.pageTitle}
  />
 </Helmet>
);

Heading semantics

Use heading tags <h1>, <h2>, ... etc the way they are intended to, not just to make the text big.

<h1>Page Title</h1>
<h2>Subtitle</h2>
<h3>Sub-subtitle</h3>
...

Unique Ids

Useful for setting focus and label/input association

const FirstName = () => (
  <div>
    <label htmlFor="first-name">First name:</label>
    <input id="first-name" />
  </div>
);

Don't rely on placeholder's as a label

Announce changes

  • When something changes, users to be aware of it

  • Use aria-live attribute

const HomePage = (props) => (
 <div
  aria-live="polite"
  aria-atomic="true"
 >
  {props.children}
 </div>
);

Manage focus

  • Ensure when routes update, window focus is set in an appropriate locaiton

  • When react router changes, the change is silent

  • Use refs to set focus and set tabIndex="-1"

class Page extends React.Component {
 focalPoint = React.createRef();

 componentDidMount() {
  this.focalPoint.current.focus();
 }

 render() {
  return (
    <section ref={this.focalPoint} tabIndex="-1">
      {/* ... */}
    </section>
  )
 }
}

How to be an a11y - Creating Accessible React Apps

By Eric Masiello

How to be an a11y - Creating Accessible React Apps

  • 184