Skip to content

Instantly share code, notes, and snippets.

@aishwarya257
Last active May 2, 2021 11:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aishwarya257/e1d01a7d8331dbb0fe19bf8beaaf9e38 to your computer and use it in GitHub Desktop.
Save aishwarya257/e1d01a7d8331dbb0fe19bf8beaaf9e38 to your computer and use it in GitHub Desktop.

Building Accessible React apps

In Recent years, many companies have started giving importance to building accessible apps. Open source libraries like Headless UI is gaining a lot of popularity for it's support on Accessibility. If you are searching for best practices to build accessible apps, then you have reached the right destination. Here, I will cover the following topics.

  • Characteristics of Good design
  • Why is Accessibility important
  • Web Accessibility standards
  • Checklist for building accessible apps
  • Accessibility tools and library

Characteristics of Good design

All companies want their products to reach a large number of users. The primary factor that one should mainly consider while designing an app is user-friendliness. If an app is easy to use, then the chances to retain or engage the users in the app would be more.

Some important characteristics of good design include:

  • Clear, Simple and Consistent workflow
  • Good color theming
  • Good error/exception handling
  • Every user feels comfortable using the app (Accessible to everyone)
  • Responsiveness

The list grows bigger and bigger... One could write a separate blog to speak about characteristics of good design.

Why is Accessibility important?

As we have seen above, building accessible apps is an important characteristic of good design. But what exactly is Accessibility? And the first answer that popup in most of our minds is "Making the app readable with screen readers". But it's not just that.

Web accessibility means designing a product in a way where every user has equal access to information and functionality irrespective of their ability. This includes people with the following disabilities:

  • Visual (Blindness, Low vision, Color blindness)
  • Cognitive (Dyslexia, Development disabilities)
  • Seizures
  • Auditory (Deafness, Hearing impairments)
  • Motor (Tremors, Muscle slowness etc.,)

Apart from building an app for everyone, if your app is accessibility compliant, then the HTML you write would be semantic which in turn boosts SEO (Search Engine Optimization) for your website and your product can also comply to Government laws

Web Accessibility standards

Web Content Accessibility Guidelines (WCAG) is a set of recommendations published by Web Accessibility Initiative (WAI) of W3C to make Web content more accessible for all kinds of people.

The accessibility guidelines principle says, "The content must be POUR" which means:

  • Perceivable (By everyone)
  • Operable (Accessible with both keyboard and mouse)
  • Understandable
  • Robust
    • App works well in current and future user tools (Technologies and devices within reasonable limits)

There are three levels of accessibility compliance in WCAG 2.1. Each of these levels have set of guidelines which is catered into three buckets like "Must have, should have and could have"

  • A: Essential
  • AA: Ideal Support
  • AAA: Specialized support

An app must adhere to at least the level A to be minimum accessibility compliant.

Checklist for building accessible apps

The following is a short summary of important points that one should bear in mind while building a web app.

Root HTML tag with lang attribute

The lang attribute is used to identify the language of the content in the website. This is useful for search engines to show language specific results and also helps screen readers to switch language profiles to provide correct accent and pronunciation.

The lang attribute can be set as follows:

<html lang="en">
  <!-- content -->
</html>

Unique title for every page

The title element within the head element should have appropriate title for every page. The websites should change the title accordingly when users navigate to different pages. Since changing title with document.title affects SEO, tools like react-helmet can be used to dynamically change title on every page.

Keyboard navigation

Keyboard navigation is a very important aspect of accessibility. Many users with disability use keyboard to access the UI elements. There are also users who are more used to using Keyboard than mouse even without disability. If your website have UI elements that are not easily accessible with keyboard, then your users may get annoyed and leave the website early. Therefore, test your UI with keyboard always when building components.

The following are some important points that needs the tested when it comes to keyboard testing.

Focus state

The UI elements should have clear focus state. So if you mark outline:none or outline:0 in CSS, make sure you provide a better focus indicator than the one provided by browsers. You can change the default focus style using :focus attribute.

Keyboard keys

All the interactive elements must be able to be activated by Keyboard with respect to the semantics of corresponding UI element. If you have defined event handlers for touch or click events, then the same action should be triggered for the corresponding keyboard actions as well.

That is, For example: if you have defined an handler for button click, then the same should be triggered for pressing Enter or Space key. Apply proper semantics for arrow keys, Tab, Shift + Tab etc.,

Avoid focus traps

Tab through the content of your website to ensure focus is not trapped within any content.

Tab order - Avoid tabindex greater than zero

The tab order should be consistent with logical flow/order of a web page.

  • A tabindex of 0 allows elements other than links and form elements to receive keyboard focus and these elements receive focus in the order it is arranged in DOM. When you want to add interactivity to elements like div or li, you must include a tabindex of 0 to make them accessible with tab key.
  • A tabindex of -1 means an element is not accessible via sequential keyboard navigation, but could be focussed with Javascript or using mouse.
  • A positive value of tabindex should always be avoided because this value determines the order in which the element can be accessed, so an element down the page can receive focus earlier than the one that is present at the top. This creates confusions and must be avoided.

Writing semantic HTML

Never use <div> for everything. HTML 5 has several useful tags like aside, main, nav, section, header, footer etc. This not only helps screen readers but also the search engines to effectively crawl and display search results.

Heading tags

A page must have only one h1 tag and the heading tags should have a logical sequence in the HTML. For example, a h4 shouldn't appear before h2 in a webpage.

Hide content correctly

Do not use display:none, or visibility:hidden or hidden attribute because they remove the content from accessibility tree making it inaccessible to screen readers. Libraries like Reach UI, Chakra UI have visually-hidden component that hides element without removing them from accessibility tree.

Icons

Every icon should have aria-label to describe it's purpose. For example, a thumbs up icon should have a aria-label or label with value "Like post". If you are using label tag instead, make sure you hide it with visually hidden css seen above.

Image with alt text

All images must have meaningful alternative text that is displayed when the image cannot be loaded

Form input controls

  • input or textarea must have a label tag or aria-label associated with it, for screen readers to read the inputs
  • The input element should have both required and aria-required for required fields and there should also be a visually indication to denote it.
  • Invalid inputs must have aria-invalid attribute when it is invalid.
  • Use aria-describedby to provide instructions for controls. Like for example, if your input should provide date in a specific format, then it should written as follows
<script src="https://gist.github.com/aishwarya257/705bf6ff2c08c3f675d16c09ba812a7a.js"></script>
  • The validation errors should always be mapped to the field it is describing, so that the assistive devices can read the information when an error is encountered. aria-describedby can be used in conjunction with role='alert' to denote errors
<script src="https://gist.github.com/aishwarya257/d3c0b8186a66434e8049439757e8513e.js"></script>

A nice blog describing the difference between aria-label, aria-labelledby and aria-describedby.

There are a lot more to explain about input controls. React Spectrum's Aria has many useful information about Accessibility with form controls

Provide skip link

A number of websites have something similar to this below.

<script src="https://gist.github.com/aishwarya257/81438f6f37bf58479524af5f0a318f1b.js"></script>

This skip link would be visible only when it is focussed with keyboard. This allows users to quickly navigate to main content without having to press Tab several times which sends focus to navigation bar and so on.

A webpage could have skip links to its important sections. For example, Twitter has skip links for "Skip to recommended content", "Skip to secondary content" etc.,

You can learn more about skip links here

Animations

Some people face problems like nausea, dizziness, and malaise because of animations used in websites. The operating system offer a solution to this problem to opt out of animations and this value can be read by browsers. For example, Apple exposes this value to browser using a media query: prefer-reduced-motion. Websites can read this value and disable the animation.

A nice article about this by Josh

Accessibility tools and library

Having known the best practices, it is always easier if at least some of these best practices are verified by some tool. Let's look at some of the tools and extensions that offer support.

Static analysis tools

eslint-plugin-jsx-a11y from the official description, it is "A Static AST checker for accessibility rules on JSX elements". Since, static analysis tools cannot check the values that change at runtime, this plugin alone cannot ensure whether a web app is completely accessibility compliant.

Libraries for React components

Use some version of axe-core to automate A11y testing. The following tools depend on axe-core

  • @axe-core/react allows you to test accessibility at runtime. You can run axe in development environment like below.

    ```ts
    if (process.env.NODE_ENV !== "production") {
      const axe = require("@axe-core/react");
      axe(React, ReactDOM, 1000);
    }
    ```
    
  • jest-axe can be used with both Enzyme and @testing-library/react. But, I highly recommend using @testing-library/react over Enzyme.

  • cypress-axe can be used to test Accessibility in the entire application for different user actions

Extensions

Deque Axe is also very handy to test accessibility on applications

Although, these tools automate some manual testing, this alone does not ensure a website is 100% accessibility compliant, we should put ourselves in the shoes of an end user and test each page/component when we develop.

And finally to wrap it up, here is an excellent video from Sara Soueidan where she explains in detail how VoiceOver tool reads the website content and how effectively can we layout elements on the page.

To conclude, building accessible websites is gaining a lot of traction and there are also laws which enforces the importance of accessibility. So, let's make web accessible to everyone irrespective of their ability :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment