How to Built
Accessible Web Apps
Tags: webdev, a11y, 100daysofcode
Published: 2021-09-11 13:25:47

In this article we will take a look how to built accessible web apps. 

## Table of Contents
1. [Semantic HTML](#1-semantic-html)
2. [Keyboard Accessible](#2-keyboard-accessible)
3. [Tab Order](#3-tab-order)
4. [Tab Index](#4-tab-index)
5. [Using Native Elements](#5-using-native-elements)
6. [Guideline for Custom Elements](#6-guideline-for-custom-elements)
7. [Screen Readers](#7-screen-readers)
8. [Labels and Aria Attributes](#8-labels-and-aria-attributes)
9. [Use Libraries and polyfills](#9-use-libraries-and-polyfills)


## 1. Semantic HTML

HTML (Hyper Text Markup Language) is exactly that: a markup language. This means that it is not only plain text, but text marked up with meaning - so called "semantics". For this, HTML offers a lot of tags, each with an inherent, unique semantic meaning. And it is absolutely crucial that those tags are used properly.

![Semantic HTML](https://cdn.hashnode.com/res/hashnode/image/upload/v1630795051989/ljYyrmHUE.jpeg?auto=compress,format&format=webp)

### 1.1. Tags with No Meanings

To understand the importance of proper semantics, let's first look at the exceptions: tags that indeed do not provide semantical information.

There are only two tags in HTML that do not have any semantic meaning: `<div>` and `<span>`. Their purpose is to offer containers needed for visual styling. And their only difference is that `<div>` is a **block element**, while `<span>` is an **inline element**.

### 1.2. Tags with Meanings

Content elements are used to give meaning to content (like headings, paragraphs, or links). Marking up text using an `<h#>` tag tells the user agent that this is not just plain text, but - in fact - a heading of a certain level!

Structural elements are used to group elements on a webpage, separating them into different regions (like **header, navigation, main, or footer**). They have been introduced in HTML 5.


[Scroll Up 🔼](#table-of-contents)

## 2. Keyboard accessible

**All the interactive elements of your page** e.g. text boxes, buttons etc should be accessible by keyboard. That means you should be able to bring focus on them by using **Tab and Shift+Tab** keys.

- Most of the interactive elements are keyboard accessible by default, i.e. browser takes care of making them keyboard ‘focus-able’.
- Non interactive elements like div, span and images are not keyboard accessibly by default. This is fine because users don’t generally need to interact with them.

[Scroll Up 🔼](#table-of-contents)

## 3. Tab Order

‌The order in which elements get focus is called tab-order. Developers need to take care that the interactive elements have logical tab-order. Tab order should follow the natural reading sequence i.e. top to bottom and right to left (for an **RTL type language**). If your tab focus is jumping around the page unpredictably then its not going to be great experience for the users.

Tab-order mainly depends on the **dom-order,** i.e. the way you have written your html. Any element which is ahead in the dom tree automatically goes ahead in the tab-order.

Sometimes people use css to make the element appear in an order which is different form dom-order. 

For Example;

```html
<!-- This will mess the tab-order. So no no! -->
<a href="#" style="float:right;">Right aligned link</a>
<a href="#">Link 1</a>
<a href="#">Link 2</a>‌
```

[Scroll Up 🔼](#table-of-contents)

## 4. Tab Index

Recommended Usage **0 for tab accessible** and **-1 for tab unaccessible**

- To make a non interactive element focusable you can give it `tabindex="0"` attribute. This not only makes the element **tab accessible** but also makes it programmatically **focusable**. That means you can call **.focus()** on that element.
- `tabindex="-1"` will take out any interactive element from tab-order. That means you can not access it through keyboard. This is particularly useful when you want to make few links/buttons inaccessible when they are behind an overlay or transitioned out of display (e.g. hamburger menus)
- Positive tabindex value makes the element tab accessible and also puts the element ahead in tab-order based on the value of the attribute. But positive tabindex values are considered anti-pattern becuase it may get very confusing more than one elements have positive tabindex values. So, **don’t** **use** positive tabindex.

### 4.1. Inert Library

**INERT** is a javascript library which makes part of the application focusable or unfocusable. Under the hood it adds `tabindex="0"` or `tabindex="-1"` to the element.

- [inert/inert.js at master · WICG/inert](https://github.com/WICG/inert/blob/master/src/inert.js)

[Scroll Up 🔼](#table-of-contents)

## 5. Use native elements

- As far as possible please use native elements for any specific purpose. That means, for example, if you need a button then just use button tag rather than making a button using divs or spans.
- Native interactive elements like buttons, select boxes etc have many built in accessibility features which you might miss if you are creating your own.

### 5.1. Native Form Elements
- [Native Form Elements](http://nativeformelements.com/)

[Scroll Up 🔼](#table-of-contents)

## 6. Guideline for custom elements
- If you must create a custom element then make sure that you go through the wai-aria best practices guide: [WAI-ARIA Authoring Practices 1.1](https://www.w3.org/TR/wai-aria-practices-1.1/)
- These guidelines tell you how the keyboard interactions should be for any element. It also has links to demo and code examples for our help.

[Button Examples](https://www.w3.org/TR/wai-aria-practices-1.1/examples/button/button.html)

[Scroll Up 🔼](#table-of-contents)

## 7. Screen readers

Screen readers are applications that will tell what is the current state of application. ...

You should take care of this;

- Many users with visual impairment rely on assistive tools like screen readers to get information on the page and to interact with page
- Always use **alt attribute** for images. Screen readers would read out the alt text for its users who have difficulty in seeing the image.
- Use proper heading tags, etc for headings, because screen readers allow users to navigate within the content of page using headings.
- Make efficient use of semantic tags like `<header>, <footer>, <section>, <nav>` etc because screen readers allow users to navigate within the content of page using these tags.
- Screen readers need to identify the interactive elements correctly so it can ask users to interact with them. For example, if you have created a button using `<button>` tag then screen reader will call it out as button. But if your button is something like `<div class="fancy button">Submit</div>` then screen reader will call it a “**group**” because div is grouping element, and user would not understand that they are supposed to interact with that element.

**How HTML elements are supported by screen readers**

- [HTML test file indexthepaciellogroup.github.io](https://thepaciellogroup.github.io/AT-browser-tests/?utm_source=html5weekly&utm_medium=email)

[Scroll Up 🔼](#table-of-contents)

## 8. **Labels and aria attributes**
There are indeed situations where standard HTML **does not** provide functionalities for all the requirements developers may have for implementing modern and interactive websites. For this, the *Accessible Rich Internet Applications (ARIA)* technical specification was introduced.

- Any code written in html not only has a visual representation but also has a semantical representation called *accessibility tree*. Accessibility tree is used by assistive tools like **screen readers** to inform the user about the accessibility properties like **type, name, state and value** of the element. The values of these accessibility properties are computed by browser based on the information provided in **html code**.

In above example name is computed by the tag. **Make use of label tag wherever applicable.**

Use **aria-label** attribute to ensure that element has a name. Suppose you have a save button which does not have a text content, then browser will not be able to compute its name. We can mention aria-label attribute to help browser compute its name.

- Similarly use different aria attributes like role, **aria-labelledby, aria-expanded, aria-checked (etc..)** to help browser compute accessibility properties:

- [WAI-ARIA Authoring Practices 1.1](https://www.w3.org/TR/wai-aria-practices-1.1/)

[Scroll Up 🔼](#table-of-contents)

## 9. **Use Libraries and polyfills**

### 9.1. Axe

- [aXe](https://chrome.google.com/webstore/detail/axe/lhdoppojpmngadmnindnejefpokejbdd) is an amazing tool to identify the accessibility gaps in your page. It is a chrome extension. Install it and use through chrome dev tools to analyse the accessibility of the page.
- Use aXe to analyse colour contrast in your page. A bad colour contrast ratio will make it difficult for few users to read the text. aXe can point out the regions of your page where the contrast does not match the [WCAG guidelines](https://www.w3.org/TR/WCAG20/#visual-audio-contrast).

### 9.2. Chrome Accessibility Inspector

- Chrome has an experimental [accessibility inspector](https://www.notion.so/0a42f815878c159517a55e6652e3b23a) in dev tools. Go to setting -> experiments in chrome dev tools to enable it. This tool helps by letting you know the computed accessibility properties
- If you want to automate the accessibility audit in your project, you can use [axe-core](https://github.com/dequelabs/axe-core). It is a node module which you can include in your build process.

### 9.3. Focus Ring

Focus-ring is the outline which gets displayed around the control when it receives focus. At times, especially with buttons, these focus rings are not very aesthetically pleasant so developers tend to disable it in css (outline:none). Mouse users wouldn’t face any issues because of this but keyboard users find it problematic because can’t figure out whether the control has focus or not. Ideally focus ring should be visible to keyboard user even if it is invisible for mouse user. 

Here is an awesome library;

- [GitHub - WICG/focus-visible: Polyfill for `:focus-visible`](https://github.com/WICG/focus-visible)

[Scroll Up 🔼](#table-of-contents)

## Screenshots

**vscode accessibility extention**
![https://gblobscdn.gitbook.com/assets%2F-Lpw2alDrsVYpWGBqlF_%2F-LvdK87UfJANojIUa1DN%2F-LvdKboX_W41O5nFKb1m%2Fcode-accessibility-warning.jpg?alt=media&token=17a66e7c-a8fa-4511-9acb-d312267e4ef2](https://gblobscdn.gitbook.com/assets%2F-Lpw2alDrsVYpWGBqlF_%2F-LvdK87UfJANojIUa1DN%2F-LvdKboX_W41O5nFKb1m%2Fcode-accessibility-warning.jpg?alt=media&token=17a66e7c-a8fa-4511-9acb-d312267e4ef2)

**Checking Accessibility With AXE**
![https://gblobscdn.gitbook.com/assets%2F-Lpw2alDrsVYpWGBqlF_%2F-LvdK87UfJANojIUa1DN%2F-LvdKsgfGXKuJcEVsLT6%2FScreen%20Shot%202019-12-09%20at%2009.18.02.png?alt=media&token=a6a1f323-f67a-4df5-a714-62cc20bc5bd0](https://gblobscdn.gitbook.com/assets%2F-Lpw2alDrsVYpWGBqlF_%2F-LvdK87UfJANojIUa1DN%2F-LvdKsgfGXKuJcEVsLT6%2FScreen%20Shot%202019-12-09%20at%2009.18.02.png?alt=media&token=a6a1f323-f67a-4df5-a714-62cc20bc5bd0)

**Checking Accessibility With AXE-2**
![https://gblobscdn.gitbook.com/assets%2F-Lpw2alDrsVYpWGBqlF_%2F-LvdK87UfJANojIUa1DN%2F-LvdKsghqU1AWtwjFjtV%2FScreen%20Shot%202019-12-09%20at%2009.20.42.png?alt=media&token=d0e87c6b-673f-4cf1-a628-7307b9948592](https://gblobscdn.gitbook.com/assets%2F-Lpw2alDrsVYpWGBqlF_%2F-LvdK87UfJANojIUa1DN%2F-LvdKsghqU1AWtwjFjtV%2FScreen%20Shot%202019-12-09%20at%2009.20.42.png?alt=media&token=d0e87c6b-673f-4cf1-a628-7307b9948592)

**Checking Accessibility With Chrome Lighthouse**
![https://gblobscdn.gitbook.com/assets%2F-Lpw2alDrsVYpWGBqlF_%2F-LvdK87UfJANojIUa1DN%2F-LvdKsgiL_Km-sYCvpHA%2FScreen%20Shot%202019-12-09%20at%2009.21.51.png?alt=media&token=b2542a0f-f047-4fd9-b5d8-96689089c766](https://gblobscdn.gitbook.com/assets%2F-Lpw2alDrsVYpWGBqlF_%2F-LvdK87UfJANojIUa1DN%2F-LvdKsgiL_Km-sYCvpHA%2FScreen%20Shot%202019-12-09%20at%2009.21.51.png?alt=media&token=b2542a0f-f047-4fd9-b5d8-96689089c766)

**Checking Accessibility With Chrome Lighthouse-2**
![https://gblobscdn.gitbook.com/assets%2F-Lpw2alDrsVYpWGBqlF_%2F-LvdK87UfJANojIUa1DN%2F-LvdKsgjsO6871vaFsOP%2FScreen%20Shot%202019-12-09%20at%2009.22.23.png?alt=media&token=43f698fa-3c72-480d-9d58-cfbfa4c748c0](https://gblobscdn.gitbook.com/assets%2F-Lpw2alDrsVYpWGBqlF_%2F-LvdK87UfJANojIUa1DN%2F-LvdKsgjsO6871vaFsOP%2FScreen%20Shot%202019-12-09%20at%2009.22.23.png?alt=media&token=43f698fa-3c72-480d-9d58-cfbfa4c748c0)
‌

[Scroll Up 🔼](#table-of-contents)

## Resources & Articles

- [Introduction to Web Accessibility](https://www.w3.org/WAI/fundamentals/accessibility-intro/)

- [Front-end Developer Handbook 2019 - Learn the entire JavaScript, CSS and HTML development practice!](https://frontendmasters.com/books/front-end-handbook/2019/#4.14)

- [9 tips to get bare minimum of web accessibility](https://medium.com/@realabhijeet4u/9-tips-to-get-bare-minimum-of-web-accessibility-739899a9437c)

- [Web Accessibility In Context - Smashing Magazine](https://www.smashingmagazine.com/2019/06/web-accessibility-context/)

- [Removing that ugly :focus ring (and keeping it too)](https://medium.com/hackernoon/removing-that-ugly-focus-ring-and-keeping-it-too-6c8727fefcd2)

- [Making a Better Custom Select Element](https://24ways.org/2019/making-a-better-custom-select-element/)

[Scroll Up 🔼](#table-of-contents)