Killing Darth Vader accessibility
Tags: webdev, a11y, javascript
Published: 2020-11-11 14:36:17

Learn useful a11y concepts and how to improve js accessibility.

First and foremost, modern JavaScript is not bad at all for a11y. Besides, you can write accessible js, and even improve a11y with it.

## What's the big deal with js?

Back in the days, websites used to have pure static HTML contents, so the only things you had to check were font size or color contrast.

With the rise of JavaScript, great features have come, but new problems too. For example, obtrusive js, inaccessible interfaces, or noisy implementations for screen readers are common concerns.

## Common misconceptions

Who the hell disable JavaScript? 

The short answer is a significant part of Internet users. BUT, be aware of three essential things:

1. They are both people with AND without disabilities
2. Many people with disabilities have JavaScript enabled
3. Disabilities can be either permanent or temporary (so it regards a lot more people)

As a result, you are probably doing it wrong if you build websites with two heads: a full-js inaccessible interface and an "accessible" non-JavaScripted version.

## Don't oversimplify a11y

A 100% a11y on lighthouse score or any other testing tool result is a start, not the ultimate certification.

A significant part of websites are said to be 100% a11y, but they are frustrating for screen reader users. 

Besides, 100% is neither a goal to pursue nor a meaningful indicator.

If you are on a Mac OS, enable VoiceOver, and you'll see what I'm talking about, even with giant platforms such as Facebook, where it's supposed to be the best you can get in terms of accessibility.

## What's the problem with screen readers?

They are different screen readers. Some of them are free and built-in in your OS (Mac, Linux, etc.). Some of them are proprietary and quite expensive (hundreds of dollars), and licenses are not for life.

Screen readers read various data on your webpage:

* visible text
* image alt attributes
* links
* headings

How is it possible? 

The browser takes the DOM tree and modifies it into a form that is useful to assistive technology, such as screen readers. The user hears a spoken representation of the app.

BTW, it is why semantic is so essential. For example, links and buttons are built-in accessibility tools because an extensive range of platforms recognize them.

[Source](https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/the-accessibility-tree)

Assistive technology is a great tool, but if you don't pay enough attention to the markup, it might become noisy and frustrating. 

A striking example is the alt attribute. If it is missing, screen readers read the image source url instead. That's one of the reasons why you need to put an alt attribute on every single image tag, even if it's empty.

Besides, screen readers read the accessibility tree in the logical order (top to bottom), so if the HTML is not in a logical order, screen readers might not be able to resolve your contents correctly.

## Write non-obtrusive js

JavaScript is a powerful language. I've seen god-like UI built with it, but also bad ones.

There are various blog posts and documentation about [Progressive enhancement](https://en.wikipedia.org/wiki/Progressive_enhancement) (	PE). 

With PE in mind, you can provide better experiences to those who can run your code with js while still offering a decent experience to users with js disabled or blocked.

It's called unobtrusive JavaScript. For example, if you write:

```html
 <a href="javascript:;" onclick="javascript:window.open('https://mysocialnetwork.com/share?url=SOMEURL', 'popup','width=600,height=600');
```
It works, but it's terrible. If js is disabled or blocked or you have an ancient browser that does not implement everything, the link is dead.

The best approach would be, IMHO, not to use it at all, but if you need to, a PE approach would recommend using an HTML class to target all links that should open a window and open them with JavaScript.

Same feature, same results, but with a better approach.

## JavaScript can introduce accessibility issues

Most of the time, inaccessible JavaScript has lousy results for navigation and user experience.

If the tab navigation is difficult or impossible, if some events trigger and the user is not fully aware of them or lacks conventional controls, then the JavaScript is probably inaccessible.

## But JavaScript can help too

There are many cases where js can help, for example, everything that involves the current state's updates. 

More pragmatically, you may want to add the `aria-expanded` attribute to let screen readers know that your submenus open and close.

You cannot do this with pure HTML, but it's relatively easy to do it with a bit of js.

Any feature that relies on js may leverage the benefits of ARIA attributes, and it's possible to take more events into account, especially the focus state.

##  ARIA for React

A challenging a11y issue with React is that screen readers ignore some changes in the application. It happens because React manipulates the DOM, but screen readers do not listen to these changes.

ARIA live regions may help in this case. Screen readers can monitor them and announce changes.

```react
<div aria-live="polite"
     aria-relevant="additions"
     aria-atomic="true">
        Important notification!
</div>
```

* the `aria-live="polite"` attribute means screen reader will finish reading out the previous notification before reading the next one
* the `aria-atomic="true"` attribute means that the screen reader must present the entire element's contents even if only part of the region changes
* the `aria-relevant="additions"` makes the screen reader watch only for additions, not removals and text changes.

[Source](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-relevant_attribute)

But where is the challenging part? It looks trivial so far.

Assistive technology needs to scan the document (~DOM) the first time to track changes in elements with `aria-live` attributes. Therefore, you cannot use JavaScript to add those attributes.

Fortunately, some dedicated npm packages exist, such as [React ARIA Alive](https://github.com/AlmeroSteyn/react-aria-live).

Once the implementation part is ok, make sure you use ARIA live region only on specific elements. Please don't put this on the body tag or some generic wrapper div. Otherwise, it will become pretty noisy.

## Wrap up

JavaScript and a11y are not enemies, and if your webpage uses JavaScript, it does not mean it's inaccessible.

If you want to run real a11y tests, using a screen reader seems a better idea than any online scan tool.

100% a11y is bullshit, but you have several ways to ease screen readers' experience and reach everyone.