Mobile accessibility - Learn web development

Mobile accessibility
====================

* Previous
* Overview: Accessibility
* Next

With web access on mobile devices being so popular and renowned platforms such as iOS and Android having full-fledged accessibility tools, it is important to consider the accessibility of your web content on these platforms. This article looks at mobile-specific accessibility considerations.

|  |  |
| --- | --- |
| Prerequisites: |
 A basic understanding of HTML, CSS, and
 JavaScript. An understanding of the
 previous articles in the course.
  |
| Objective: |
 To understand what problems exist with accessibility on mobile devices,
 and how to overcome them.
  |

Accessibility on mobile devices
-------------------------------

The state of accessibility — and support for web standards in general — is good in modern mobile devices. Long gone are the days when mobile devices ran completely different web technologies to desktop browsers, forcing developers to use browser sniffing and serve them completely separate sites (although quite a few companies still detect usage of mobile devices and serve them a separate mobile domain).

These days, mobile devices can usually handle fully-featured websites, and the main platforms even have screen readers built in to enable visually impaired users to use them successfully. Modern mobile browsers tend to have good support for WAI-ARIA, too.

To make a website accessible and usable on mobile, you just need to follow general good web design and accessibility best practices.

There are some exceptions that need special consideration for mobile; the main ones are:

* Control mechanisms — Make sure interface controls such as buttons are accessible on mobiles (i.e., mainly touchscreen), as well as desktops/laptops (mainly mouse/keyboard).
* User input — Make user input requirements as painless as possible on mobile (e.g., in forms, keep typing to a minimum).
* Responsive design — Make sure layouts work on mobile, conserve image download sizes, and think about the provision of images for high-resolution screens.
Summary of screen reader testing on Android and iOS
---------------------------------------------------

The most common mobile platforms have fully functional screen readers. These function in much the same way as desktop screen readers, except they are largely operated using touch gestures rather than key combinations.

Let's look at the main two: TalkBack on Android and VoiceOver on iOS.

### Android TalkBack

The TalkBack screen reader is built into the Android operating system.

To turn it on, look up what phone model and Android version you have, and then look up where the TalkBack menu is. It tends to differ widely between Android versions and even between different phone models. Some phone manufacturers (e.g. Samsung) don't even have TalkBack in newer phones, and instead opted for their own screen reader.

When you've found the TalkBack menu, press the slider switch to turn TalkBack on. Follow any additional on-screen prompts that you are presented with.

When TalkBack is turned on, your Android device's basic controls will be a bit different. For example:

1. Single-tapping an app will select it, and the device will read out what the app is.
2. Swiping left and right will move between apps, or buttons/controls if you are in a control bar. The device will read out each option.
3. Double-tapping anywhere will open the app/select the option.
4. You can also "explore by touch" — hold your finger down on the screen and drag it around, and your device will read out the different apps/items you move across.

If you want to turn TalkBack off:

1. Navigate back to the TalkBack menu screen (using the different gestures that are currently enabled.)
2. Navigate to the slider switch and activate it to turn it off.

**Note:** You can get to your home screen at any time by swiping up and left in a smooth motion. If you have more than one home screen, you can move between them by swiping two fingers left and right.

For a more complete list of TalkBack gestures, see Use TalkBack gestures.

#### Unlocking the phone

When TalkBack is turned on, unlocking the phone is a bit different.

You can do a two-finger swipe up from the bottom of the lock screen. If you've set a passcode or pattern for unlocking your device, you will then be taken to the relevant entry screen to enter it.

You can also explore by touch to find the *Unlock* button at the bottom middle of the screen, and then double-tap.

#### Global and local menus

TalkBack allows you to access global and local context menus, wherever you have navigated on the device. The former provides global options relating to the device as a whole, and the latter provides options relating just to the current app/screen you are in.

To get to these menus:

1. Access the global menu by quickly swiping down, and then right.
2. Access the local menu by quickly swiping up, and then right.
3. Swipe left and right to cycle between the different options.
4. Once you've selected the option you want, double-tap to choose that option.

For details on all the options available under the global and local context menus, see Use global and local context menus.

#### Browsing web pages

You can use the local context menu while in a web browser to find options to navigate web pages using just the headings, form controls, or links, or navigate line by line, etc.

For example, with TalkBack turned on:

1. Open your web browser.
2. Activate the URL bar.
3. Enter a web page that has a bunch of headings on it, such as the front page of bbc.co.uk. To enter the text of the URL:
    * Select the URL bar by swiping left/right till you get to it, and then double-tapping.
    * Hold your finger down on the virtual keyboard until you get the character you want, and then release your finger to type it. Repeat for each character.
    * Once you've finished, find the Enter key and press it.
4. Swipe left and right to move between different items on the page.
5. Swipe up and right with a smooth motion to enter the local content menu.
6. Swipe right until you find the "Headings and Landmarks" option.
7. Double-tap to select it. Now you'll be able to swipe left and right to move between headings and ARIA landmarks.
8. To go back to the default mode, enter the local context menu again by swiping up and right, select "Default", and then double-tap to activate.

**Note:** See Get started on Android with TalkBack for more complete documentation.

### iOS VoiceOver

A mobile version of VoiceOver is built into the iOS operating system.

To turn it on, go to Your *Settings* app and select *Accessibility > VoiceOver*. Press the *VoiceOver* slider to enable it (you'll also see several other options related to VoiceOver on this page).

**Note:** Some older iOS devices have the VoiceOver menu at *Settings app* > *General* > *Accessibility* > *VoiceOver*.

Once VoiceOver is enabled, iOS's basic control gestures will be a bit different:

1. A single tap will cause the item you tap on to be selected; your device will speak the item you've tapped on.
2. You can also navigate the items on the screen by swiping left and right to move between them, or by sliding your finger around on the screen to move between different items (when you find the item you want, you can remove your finger to select it).
3. To activate the selected item (e.g., open a selected app), double-tap anywhere on the screen.
4. Swipe with three fingers to scroll through a page.
5. Tap with two fingers to perform a context-relevant action — for example, taking a photo while in the camera app.

To turn it off again, navigate back to *Settings > General > Accessibility > VoiceOver* using the above gestures, and toggle the *VoiceOver* slider back to off.

#### Unlock phone

To unlock the phone, you need to press the home button (or swipe) as normal. If you have a passcode set, you can select each number by swiping/sliding (as explained above) and then double-tapping to enter each number when you've found the right one.

#### Using the Rotor

When VoiceOver is turned on, you have a navigation feature called the Rotor available to you, which allows you to quickly choose from a number of common useful options. To use it:

1. Twist two fingers around on the screen like you are turning a dial. Each option will be read aloud as you twist further around. You can go back and forth to cycle through the options.
2. Once you've found the option you want:
    * Release your fingers to select it.
    * If it is an option you can iterate the value of (such as Volume or Speaking Rate), you can do a swipe up or down to increase or decrease the value of the selected item.

The options available under the Rotor are context-sensitive — they will differ depending on what app or view you are in (see below for an example).

#### Browsing web pages

Let's have a go at web browsing with VoiceOver:

1. Open your web browser.
2. Activate the URL bar.
3. Enter a web page that has a bunch of headings on it, such as the front page of bbc.co.uk. To enter the text of the URL:
    * Select the URL bar by swiping left/right until you get to it, and then double-tapping.
    * For each character, hold your finger down on the virtual keyboard until you get the character you want, and then release your finger to select it. Double-tap to type it.
    * Once you've finished, find the Enter key and press it.
4. Swipe left and right to move between items on the page. You can double-tap an item to select it (e.g., follow a link).
5. By default, the selected Rotor option will be Speaking Rate; you can currently swipe up and down to increase or decrease the speaking rate.
6. Now turn two fingers around the screen like a dial to show the rotor and move between its options. Here are a few examples of the options available:
    * *Speaking Rate*: Change the speaking rate.
    * *Containers*: Move between different semantic containers on the page.
    * *Headings*: Move between headings on the page.
    * *Links*: Move between links on the page.
    * *Form Controls*: Move between form controls on the page.
    * *Language*: Move between different translations, if they are available.
7. Select *Headings*. Now you'll be able to swipe up and down to move between headings on the page.

**Note:** For a more complete reference covering the VoiceOver gestures available and other hints on accessibility testing on iOS, see Test Accessibility on Your Device with VoiceOver.

Control mechanisms
------------------

In our CSS and JavaScript accessibility article, we looked at the idea of events that are specific to a certain type of control mechanism (see Mouse-specific events). To recap, these cause accessibility issues because other control mechanisms can't activate the associated functionality.

As an example, the click event is good in terms of accessibility — an associated event handler can be invoked by clicking the element the handler is set on, tabbing to it and pressing Enter/Return, or tapping it on a touchscreen device. Try our simple-button-example.html example (see it running live) to see what we mean.

Alternatively, mouse-specific events such as mousedown and mouseup create problems — their event handlers cannot be invoked using non-mouse controls.

If you try to control our simple-box-drag.html (see example live) example with a keyboard or touch, you'll see the problem. This occurs because we are using code such as the following:

```js
div.onmousedown = () => {
  initialBoxX = div.offsetLeft;
  initialBoxY = div.offsetTop;
  movePanel();
};

document.onmouseup = stopMove;
```

To enable other forms of control, you need to use different, yet equivalent events — for example, touch events work on touchscreen devices:

```js
div.ontouchstart = (e) => {
  initialBoxX = div.offsetLeft;
  initialBoxY = div.offsetTop;
  positionHandler(e);
  movePanel();
};

panel.ontouchend = stopMove;
```

We've provided a simple example that shows how to use the mouse and touch events together — see multi-control-box-drag.html (see the example live also).

**Note:** You can also see fully functional examples showing how to implement different control mechanisms at Implementing game control mechanisms.

Responsive design
-----------------

Responsive design is the practice of making your layouts and other features of your apps dynamically change depending on factors such as screen size and resolution, so they are usable and accessible to users of different device types.

In particular, the most common problems that need to be addressed for mobile are:

* Suitability of layouts for mobile devices. A multi-column layout won't work as well on a narrow screen, for example, and the text size may need to be increased so it is legible. Such issues can be solved by creating a responsive layout using technologies such as media queries, viewport, and flexbox.
* Conserving image sizes downloaded. In general, small-screen devices won't need images that are as large as their desktop counterparts, and they are more likely to be on slow network connections. Therefore, it is wise to serve smaller images to narrow screen devices as appropriate. You can handle this using responsive image techniques.
* Thinking about high resolutions. Many mobile devices have high-resolution screens, and therefore need higher-resolution images so that the display can continue to look crisp and sharp. Again, you can serve images as appropriate using responsive image techniques. In addition, many image requirements can be fulfilled using the SVG vector images format, which is well-supported across browsers today. SVG has a small file size and will stay sharp regardless of whatever size is being displayed (see Adding vector graphics to the web for more details).

**Note:** We won't provide a full discussion of responsive design techniques here, as they are covered in other places around MDN (see the above links).

### Specific mobile considerations

There are other important issues to consider when making sites more accessible on mobile. We have listed a couple here, but we will add more when we think of them.

#### Not disabling zoom

Using viewport, it is possible to disable zoom. Always ensure resizing is enabled, and set the width to the device's width in the `<head>`:

```html
<meta name="viewport" content="width=device-width; user-scalable=yes" />
```

You should never set `user-scalable=no` if at all possible — many people rely on zoom to be able to see the content of your website, so taking this functionality away is a really bad idea. There are certain situations where zooming might break the UI; in such cases, if you feel that you need to disable zoom, you should provide some other kind of equivalent, such as a control for increasing the text size in a way that doesn't break your UI.

#### Keeping menus accessible

Because the screen is so much narrower on mobile devices, it is very common to use media queries and other technologies to make the navigation menu shrink down to a tiny icon at the top of the display — which can be pressed to reveal the menu only if it's needed — when the site is viewed on mobile. This is commonly represented by a "three horizontal lines" icon, and the design pattern is consequently known as a "hamburger menu".

When implementing such a menu, you need to make sure that the control to reveal it is accessible by appropriate control mechanisms (normally touch for mobile), as discussed in Control mechanisms above, and that the rest of the page is moved out of the way or hidden in some way while the menu is being accessed, to avoid confusion with navigating it.

Click here for a good hamburger menu example.

User input
----------

On mobile devices, inputting data tends to be more annoying for users than the equivalent experience on desktop computers. It is more convenient to type text into form inputs using a desktop or laptop keyboard than a touchscreen virtual keyboard or a tiny mobile physical keyboard.

For this reason, it is worth trying to minimize the amount of typing needed. As an example, instead of getting users to fill out their job title each time using a regular text input, you could instead offer a `<select>` menu containing the most common options (which also helps with consistency in data entry) and offer an "Other" option that displays a text field to type any outliers into. You can see a simple example of this idea in action in common-job-types.html (see the common jobs example live).

It is also worth considering the use of HTML form input types such as the date on mobile platforms as they handle them well — both Android and iOS, for example, display usable widgets that fit well with the device experience. See html5-form-examples.html for some examples (see the HTML5 form examples live) — try loading these and manipulating them on mobile devices. For example:

* Types `number`, `tel`, and `email` display suitable virtual keyboards for entering numbers/telephone numbers.
* Types `time` and `date` display suitable pickers for selecting times and dates.

If you want to provide a different solution for desktops, you could always serve different markup to your mobile devices using feature detection. See input types for raw information on detecting different input types, and also check out our feature detection article for much more information.

Summary
-------

In this article, we have provided you with some details about common mobile accessibility-specific issues and how to overcome them. We also took you through the usage of the most common screen readers to aid you in accessibility testing.

See also
--------

* Guidelines For Mobile Web Development — A list of articles in *Smashing Magazine* covering different techniques for mobile web design.
* Make your site work on touch devices — Useful article about using touch events to get interactions working on mobile devices.
* Previous
* Overview: Accessibility
* Next


WAI-ARIA basics - Learn web development

WAI-ARIA basics
===============

* Previous
* Overview: Accessibility
* Next

Following on from the previous article, sometimes making complex UI controls that involve unsemantic HTML and dynamic JavaScript-updated content can be difficult. WAI-ARIA is a technology that can help with such problems by adding in further semantics that browsers and assistive technologies can recognize and use to let users know what is going on. Here we'll show how to use it at a basic level to improve accessibility.

|  |  |
| --- | --- |
| Prerequisites: |
 A basic understanding of HTML, CSS, and
 JavaScript. An understanding of the
 previous articles in the course.
  |
| Objective: |
 To gain familiarity with WAI-ARIA, and how it can be used to provide
 useful additional semantics to enhance accessibility where required.
  |

What is WAI-ARIA?
-----------------

Let's start by looking at what WAI-ARIA is, and what it can do for us.

### A whole new set of problems

As web apps started to get more complex and dynamic, a new set of accessibility features and problems started to appear.

For example, HTML introduced a number of semantic elements to define common page features (`<nav>`, `<footer>`, etc.). Before these were available, developers would use `<div>`s with IDs or classes, e.g. `<div class="nav">`, but these were problematic, as there was no easy way to easily find a specific page feature such as the main navigation programmatically.

The initial solution was to add one or more hidden links at the top of the page to link to the navigation (or whatever else), for example:

```html
<a href="#hidden" class="hidden">Skip to navigation</a>
```

But this is still not very precise, and can only be used when the screen reader is reading from the top of the page.

As another example, apps started to feature complex controls like date pickers for choosing dates, sliders for choosing values, etc. HTML provides special input types to render such controls:

```html
<input type="date" /> <input type="range" />
```

These were originally not well-supported and it was, and still is to a lesser extent, difficult to style them, leading designers and developers to opt for custom solutions. Instead of using these native features, some developers rely on JavaScript libraries that generate such controls as a series of nested `<div>`s which are then styled using CSS and controlled using JavaScript.

The problem here is that visually they work, but screen readers can't make any sense of what they are at all, and their users just get told that they can see a jumble of elements with no semantics to describe what they mean.

### Enter WAI-ARIA

WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) is a specification written by the W3C, defining a set of additional HTML attributes that can be applied to elements to provide additional semantics and improve accessibility wherever it is lacking. There are three main features defined in the spec:

Roles

These define what an element is or does. Many of these are so-called landmark roles, which largely duplicate the semantic value of structural elements, such as `role="navigation"` (`<nav>`) or `role="complementary"` (`<aside>`). Some other roles describe different page structures, such as `role="banner"`, `role="search"`, `role="tablist"`, and `role="tabpanel"`, which are commonly found in UIs.

Properties

These define properties of elements, which can be used to give them extra meaning or semantics. As an example, `aria-required="true"` specifies that a form input needs to be filled in order to be valid, whereas `aria-labelledby="label"` allows you to put an ID on an element, then reference it as being the label for anything else on the page, including multiple elements, which is not possible using `<label for="input">`. As an example, you could use `aria-labelledby` to specify that a key description contained in a `<div>` is the label for multiple table cells, or you could use it as an alternative to image alt text — specify existing information on the page as an image's alt text, rather than having to repeat it inside the `alt` attribute. You can see an example of this at Text alternatives.

States

Special properties that define the current conditions of elements, such as `aria-disabled="true"`, which specifies to a screen reader that a form input is currently disabled. States differ from properties in that properties don't change throughout the lifecycle of an app, whereas states can change, generally programmatically via JavaScript.

An important point about WAI-ARIA attributes is that they don't affect anything about the web page, except for the information exposed by the browser's accessibility APIs (where screen readers get their information from). WAI-ARIA doesn't affect webpage structure, the DOM, etc., although the attributes can be useful for selecting elements by CSS.

**Note:** You can find a useful list of all the ARIA roles and their uses, with links to further information, in the WAI-ARIA spec — see Definition of Roles — on this site — see ARIA roles.

The spec also contains a list of all the properties and states, with links to further information — see Definitions of States and Properties (all `aria-*` attributes).

### Where is WAI-ARIA supported?

This is not an easy question to answer. It is difficult to find a conclusive resource that states what features of WAI-ARIA are supported, and where, because:

1. There are a lot of features in the WAI-ARIA spec.
2. There are many combinations of operating systems, browsers, and screen readers to consider.

This last point is key — To use a screen reader in the first place, your operating system needs to run browsers that have the necessary accessibility APIs in place to expose the information screen readers need to do their job. Most popular OSes have one or two browsers in place that screen readers can work with. The Paciello Group has a fairly up-to-date post that provides data for this — see Rough Guide: browsers, operating systems and screen reader support updated.

Next, you need to worry about whether the browsers in question support ARIA features and expose them via their APIs, but also whether screen readers recognize that information and present it to their users in a useful way.

1. Browser support is almost universal.
2. Screen reader support for ARIA features isn't quite at this level, but the most popular screen readers are getting there. You can get an idea of support levels by looking at Powermapper's WAI-ARIA Screen reader compatibility article.

In this article, we won't attempt to cover every WAI-ARIA feature, and its exact support details. Instead, we will cover the most critical WAI-ARIA features for you to know about; if we don't mention any support details, you can assume that the feature is well-supported. We will clearly mention any exceptions to this.

**Note:** Some JavaScript libraries support WAI-ARIA, meaning that when they generate UI features like complex form controls, they add ARIA attributes to improve the accessibility of those features. If you are looking for a 3rd party JavaScript solution for rapid UI development, you should definitely consider the accessibility of its UI widgets as an important factor when making your choice. Good examples are jQuery UI (see About jQuery UI: Deep accessibility support), ExtJS, and Dojo/Dijit.

### When should you use WAI-ARIA?

We talked about some of the problems that prompted WAI-ARIA to be created earlier on, but essentially, there are four main areas that WAI-ARIA is useful in:

Signposts/Landmarks

ARIA's `role` attribute values can act as landmarks that either replicate the semantics of HTML elements (e.g., `<nav>`), or go beyond HTML semantics to provide signposts to different functional areas, for example, `search`, `tablist`, `tab`, `listbox`, etc.

Dynamic content updates

Screen readers tend to have difficulty with reporting constantly changing content; with ARIA we can use `aria-live` to inform screen reader users when an area of content is updated dynamically: for example, by JavaScript in the page fetching new content from the server and updating the DOM.

Enhancing keyboard accessibility

There are built-in HTML elements that have native keyboard accessibility; when other elements are used along with JavaScript to simulate similar interactions, keyboard accessibility and screen reader reporting suffers as a result. Where this is unavoidable, WAI-ARIA provides a means to allow other elements to receive focus (using `tabindex`).

Accessibility of non-semantic controls

When a series of nested `<div>`s along with CSS/JavaScript is used to create a complex UI-feature, or a native control is greatly enhanced/changed via JavaScript, accessibility can suffer — screen reader users will find it difficult to work out what the feature does if there are no semantics or other clues. In these situations, ARIA can help to provide what's missing with a combination of roles like `button`, `listbox`, or `tablist`, and properties like `aria-required` or `aria-posinset` to provide further clues as to functionality.

One thing to remember though — **you should only use WAI-ARIA when you need to!** Ideally, you should *always* use native HTML features to provide the semantics required by screen readers to tell their users what is going on. Sometimes this isn't possible, either because you have limited control over the code, or because you are creating something complex that doesn't have an easy HTML element to implement it. In such cases, WAI-ARIA can be a valuable accessibility enhancing tool.

But again, only use it when necessary!

**Note:** Also, try to make sure you test your site with a variety of *real* users — non-disabled people, people using screen readers, people using keyboard navigation, etc. They will have better insights than you about how well it works.

Practical WAI-ARIA implementations
----------------------------------

In the next section, we'll look at the four areas in more detail, along with practical examples. Before you continue, you should get a screen reader testing setup put in place, so you can test some of the examples as you go through.

See our section on testing screen readers for more information.

### Signposts/Landmarks

WAI-ARIA adds the `role` attribute to browsers, which allows you to add extra semantic value to elements on your site wherever they are needed. The first major area in which this is useful is providing information for screen readers so that their users can find common page elements. Let's look at an example — our website-no-roles example (see it live) has the following structure:

```html
<header>
  <h1>…</h1>
  <nav>
    <ul>
      …
    </ul>
    <form>
      <!-- search form -->
    </form>
  </nav>
</header>

<main>
  <article>…</article>
  <aside>…</aside>
</main>

<footer>…</footer>
```

If you try testing the example with a screen reader in a modern browser, you'll already get some useful information. For example, VoiceOver gives you the following:

* On the `<header>` element — "banner, 2 items" (it contains a heading and the `<nav>`).
* On the `<nav>` element — "navigation 2 items" (it contains a list and a form).
* On the `<main>` element — "main 2 items" (it contains an article and an aside).
* On the `<aside>` element — "complementary 2 items" (it contains a heading and a list).
* On the search form input — "Search query, insertion at beginning of text".
* On the `<footer>` element — "footer 1 item".

If you go to VoiceOver's landmarks menu (accessed using VoiceOver key + U and then using the cursor keys to cycle through the menu choices), you'll see that most of the elements are nicely listed so they can be accessed quickly.

![Mac's VoiceOver menu for quick accessibility. Landmarks header and landmarks list including banner, navigation, main, and complementary.](/en-US/docs/Learn/Accessibility/WAI-ARIA_basics/landmarks-list.png)

However, we could do better here. The search form is a really important landmark that people will want to find, but it is not listed in the landmarks menu or treated like a notable landmark beyond the actual input being called out as a search input (`<input type="search">`).

Let's improve it by the use of some ARIA features. First, we'll add some `role` attributes to our HTML structure. You can try taking a copy of our original files (see `index.html` and `style.css`), or navigating to our website-aria-roles example (see it live), which has a structure like this:

```html
<header>
  <h1>…</h1>
  <nav role="navigation">
    <ul>
      …
    </ul>
    <form role="search">
      <!-- search form -->
    </form>
  </nav>
</header>

<main>
  <article role="article">…</article>
  <aside role="complementary">…</aside>
</main>

<footer>…</footer>
```

We've also given you a bonus feature in this example — the `<input>` element has been given the attribute `aria-label`, which gives it a descriptive label to be read out by a screen reader, even though we haven't included a `<label>` element. In cases like these, this is very useful — a search form like this one is a very common, easily recognized feature, and adding a visual label would spoil the page design.

```html
<input
 type="search"
 name="q"
 placeholder="Search query"
 aria-label="Search through site content" />
```

Now if we use VoiceOver to look at this example, we get some improvements:

* The search form is called out as a separate item, both when browsing through the page, and in the Landmarks menu.
* The label text contained in the `aria-label` attribute is read out when the form input is highlighted.

Beyond this, the site is more likely to be accessible to users of older browsers such as IE8; it is worth including ARIA roles for that purpose. And if for some reason your site is built using just `<div>`s, you should definitely include the ARIA roles to provide these much needed semantics!

The improved semantics of the search form have shown what is made possible when ARIA goes beyond the semantics available in HTML. You'll see a lot more about these semantics and the power of ARIA properties/attributes below, especially in the Accessibility of non-semantic controls section. For now though, let's look at how ARIA can help with dynamic content updates.

### Dynamic content updates

Content loaded into the DOM can be easily accessed using a screen reader, from textual content to alternative text attached to images. Traditional static websites with largely text content are therefore easy to make accessible for people with visual impairments.

The problem is that modern web apps are often not just static text — they often update parts of the page by fetching new content from the server and updating the DOM. These are sometimes referred to as **live regions**.

Let's look at a quick example — see `aria-no-live.html` (also see it running live). In this example, we have a simple random quote box:

```html
<section>
  <h1>Random quote</h1>
  <blockquote>
    <p></p>
  </blockquote>
</section>
```

Our JavaScript uses the `fetch()` API to load a JSON file via containing a series of random quotes and their authors. Once that is done, we start up a `setInterval()` loop that loads a new random quote into the quote box every 10 seconds:

```js
const intervalID = setInterval(showQuote, 10000);
```

This works OK, but it is not good for accessibility — the content update is not detected by screen readers, so their users would not know what is going on. This is a fairly trivial example, but just imagine if you were creating a complex UI with lots of constantly updating content, like a chat room, or a strategy game UI, or a live updating shopping cart display — it would be impossible to use the app in any effective way without some kind of way of alerting the user to the updates.

WAI-ARIA, fortunately, provides a useful mechanism to provide these alerts — the `aria-live` property. Applying this to an element causes screen readers to read out the content that is updated. How urgently the content is read out depends on the attribute value:

`off`

The default. Updates should not be announced.

`polite`

Updates should be announced only if the user is idle.

`assertive`

Updates should be announced to the user as soon as possible.

We'd like you to take a copy of `aria-no-live.html` and `quotes.json`, and update your `<section>` opening tag as follows:

```html
<section aria-live="assertive">…</section>
```

This will cause a screen reader to read out the content as it is updated.

**Note:** Most browsers will throw a security exception if you try to make an HTTP request from a `file://` URL, e.g. if you just load the file by loading it directly into the browser (via double clicking, etc.). See how to set up a local testing server.

There is an additional consideration here — only the bit of text that updates is read out. It might be nice if we always read out the heading too, so the user can remember what is being read out. To do this, we can add the `aria-atomic` property to the section. Update your `<section>` opening tag again, like so:

```html
<section aria-live="assertive" aria-atomic="true">…</section>
```

The `aria-atomic="true"` attribute tells screen readers to read out the entire element contents as one atomic unit, not just the bits that were updated.

**Note:** You can see the finished example at `aria-live.html` (see it running live).

**Note:** The `aria-relevant` property is also quite useful for controlling what gets read out when a live region is updated. You can for example only get content additions or removals read out.

### Enhancing keyboard accessibility

As discussed in a few other places in the module, one of the key strengths of HTML with respect to accessibility is the built-in keyboard accessibility of features such as buttons, form controls, and links. Generally, you can use the tab key to move between controls, the Enter/Return key to select or activate controls, and occasionally other controls as needed (for example the up and down cursor to move between options in a `<select>` box).

However, sometimes you will end up having to write code that either uses non-semantic elements as buttons (or other types of control), or uses focusable controls for not quite the right purpose. You might be trying to fix some bad code you've inherited, or you might be building some kind of complex widget that requires it.

In terms of making non-focusable code focusable, WAI-ARIA extends the `tabindex` attribute with some new values:

* `tabindex="0"` — as indicated above, this value allows elements that are not normally tabbable to become tabbable. This is the most useful value of `tabindex`.
* `tabindex="-1"` — this allows not normally tabbable elements to receive focus programmatically, e.g. via JavaScript, or as the target of links.

We discussed this in more detail and showed a typical implementation back in our HTML accessibility article — see Building keyboard accessibility back in.

### Accessibility of non-semantic controls

This follows on from the previous section — when a series of nested `<div>`s along with CSS/JavaScript is used to create a complex UI-feature, or a native control is greatly enhanced/changed via JavaScript, not only can keyboard accessibility suffer, but screen reader users will find it difficult to work out what the feature does if there are no semantics or other clues. In such situations, ARIA can help to provide those missing semantics.

#### Form validation and error alerts

First of all, let's revisit the form example we first looked at in our CSS and JavaScript accessibility article (read Keeping it unobtrusive for a full recap). At the end of this section, we showed that we have included some ARIA attributes on the error message box that displays any validation errors when you try to submit the form:

```html
<div class="errors" role="alert" aria-relevant="all">
  <ul></ul>
</div>
```

* `role="alert"` automatically turns the element it is applied to into a live region, so changes to it are read out; it also semantically identifies it as an alert message (important time/context-sensitive information), and represents a better, more accessible way of delivering an alert to a user (modal dialogs like `alert()` calls have a number of accessibility problems; see Popup Windows by WebAIM).
* An `aria-relevant` value of `all` instructs the screen reader to read out the contents of the error list when any changes are made to it — i.e., when errors are added or removed. This is useful because the user will want to know what errors are left, not just what has been added or removed from the list.

We could go further with our ARIA usage, and provide some more validation help. How about indicating whether fields are required in the first place, and what range the age should be?

1. At this point, take a copy of our `form-validation.html` and `validation.js` files, and save them in a local directory.
2. Open them both in a text editor and have a look at how the code works.
3. First of all, add a paragraph just above the opening `<form>` tag, like the one below, and mark both the form `<label>`s with an asterisk. This is normally how we mark required fields for sighted users.

```html
<p>Fields marked with an asterisk (*) are required.</p>
```

4. This makes visual sense, but it isn't as easy to understand for screen reader users. Fortunately, WAI-ARIA provides the `aria-required` attribute to give screen readers hints that they should tell users that form inputs need to be filled in. Update the `<input>` elements like so:

```html
<input type="text" name="name" id="name" aria-required="true" />

<input type="number" name="age" id="age" aria-required="true" />
```

5. If you save the example now and test it with a screen reader, you should hear something like "Enter your name star, required, edit text".
6. It might also be useful if we give screen reader users and sighted users an idea of what the age value should be. This is often presented as a tooltip or placeholder inside the form field. WAI-ARIA does include `aria-valuemin` and `aria-valuemax` properties to specify min and max values, and screen readers support the native `min` and `max` attributes. Another well-supported feature is the HTML `placeholder` attribute, which can contain a message that is shown in the input when no value is entered and is read out by a few screen readers. Update your number input like this:

```html
<label for="age">Your age:</label>
<input
 type="number"
 name="age"
 id="age"
 placeholder="Enter 1 to 150"
 required
 aria-required="true" />
```

Always include a `<label>` for every input. While some screen readers announce the placeholder text, most do not. Acceptable substitutions for providing form controls with an accessible name include `aria-label` and `aria-labelledby`. But the `<label>` element with a `for` attribute is the preferred method as it provides usability for all users, including mouse users.

**Note:** You can see the finished example live at `form-validation-updated.html`.

WAI-ARIA also enables some advanced form labelling techniques, beyond the classic `<label>` element. We already talked about using the `aria-label` property to provide a label where we don't want the label to be visible to sighted users (see the Signposts/Landmarks section, above). Some other labeling techniques use other properties such as `aria-labelledby` if you want to designate a non-`<label>` element as a label or label multiple form inputs with the same label, and `aria-describedby`, if you want to associate other information with a form input and have it read out as well. See WebAIM's Advanced Form Labeling article for more details.

There are many other useful properties and states too, for indicating the status of form elements. For example, `aria-disabled="true"` can be used to indicate that a form field is disabled. Many browsers will skip past disabled form fields which leads to them not being read out by screen readers. In some cases, a disabled element will be perceived, so it is a good idea to include this attribute to let the screen reader know that a disabled form control is in fact disabled.

If the disabled state of an input is likely to change, then it is also a good idea to indicate when it happens, and what the result is. For example, in our `form-validation-checkbox-disabled.html` demo, there is a checkbox that when checked, enables another form input to allow further information to be entered. We've set up a hidden live region:

```html
<p class="hidden-alert" aria-live="assertive"></p>
```

which is hidden from view using absolute positioning. When this is checked/unchecked, we update the text inside the hidden live region to tell screen reader users what the result of checking this checkbox is, as well as updating the `aria-disabled` state, and some visual indicators too:

```js
function toggleMusician(bool) {
  const instruItem = formItems[formItems.length - 1];
  if (bool) {
    instruItem.input.disabled = false;
    instruItem.label.style.color = "#000";
    instruItem.input.setAttribute("aria-disabled", "false");
    hiddenAlert.textContent =
      "Instruments played field now enabled; use it to tell us what you play.";
  } else {
    instruItem.input.disabled = true;
    instruItem.label.style.color = "#999";
    instruItem.input.setAttribute("aria-disabled", "true");
    instruItem.input.removeAttribute("aria-label");
    hiddenAlert.textContent = "Instruments played field now disabled.";
  }
}
```

#### Describing non-semantic buttons as buttons

A few times in this course already, we've mentioned the native accessibility of (and the accessibility issues behind using other elements to fake) buttons, links, or form elements (see UI controls in the HTML accessibility article, and Enhancing keyboard accessibility, above). Basically, you can add keyboard accessibility back in without too much trouble in many cases, using `tabindex` and a bit of JavaScript.

But what about screen readers? They still won't see the elements as buttons. If we test our `fake-div-buttons.html` example in a screen reader, our fake buttons will be reported using phrases like "Click me!, group", which is obviously confusing.

We can fix this using a WAI-ARIA role. Make a local copy of `fake-div-buttons.html`, and add `role="button"` to each button `<div>`, for example:

```html
<div data-message="This is from the first button" tabindex="0" role="button">
  Click me!
</div>
```

Now when you try this using a screen reader, you'll have buttons be reported using phrases like "Click me!, button". While this is much better, you still have to add in all the native button features users expect, like handling `enter` and click events, as explained in the `button` role documentation.

**Note:** Don't forget however that using the correct semantic element where possible is always better. If you want to create a button, and can use a `<button>` element, you should use a `<button>` element!

#### Guiding users through complex widgets

There are a whole host of other roles that can identify non-semantic element structures as common UI features that go beyond what's available in standard HTML, for example `combobox`, `slider`, `tabpanel`, `tree`. You can see several useful examples in the Deque university code library to give you an idea of how such controls can be made accessible.

Let's go through an example of our own. We'll return to our simple absolutely-positioned tabbed interface (see Hiding things in our CSS and JavaScript accessibility article), which you can find at Tabbed info box example (see source code).

This example as-is works fine in terms of keyboard accessibility — you can happily tab between the different tabs and select them to show the tab contents. It is also fairly accessible too — you can scroll through the content and use the headings to navigate, even if you can't see what is happening on screen. It is however not that obvious what the content is — a screen reader currently reports the content as a list of links, and some content with three headings. It doesn't give you any idea of what the relationship is between the content. Giving the user more clues as to the structure of the content is always good.

To improve things, we've created a new version of the example called `aria-tabbed-info-box.html` (see it running live). We've updated the structure of the tabbed interface like so:

```html
<ul role="tablist">
  <li
 class="active"
 role="tab"
 aria-selected="true"
 aria-setsize="3"
 aria-posinset="1"
 tabindex="0">
    Tab 1
  </li>
  <li
 role="tab"
 aria-selected="false"
 aria-setsize="3"
 aria-posinset="2"
 tabindex="0">
    Tab 2
  </li>
  <li
 role="tab"
 aria-selected="false"
 aria-setsize="3"
 aria-posinset="3"
 tabindex="0">
    Tab 3
  </li>
</ul>
<div class="panels">
  <article class="active-panel" role="tabpanel" aria-hidden="false">…</article>
  <article role="tabpanel" aria-hidden="true">…</article>
  <article role="tabpanel" aria-hidden="true">…</article>
</div>
```

**Note:** The most striking change here is that we've removed the links that were originally present in the example, and just used the list items as the tabs — this was done because it makes things less confusing for screen reader users (the links don't really take you anywhere; they just change the view), and it allows the setsize/position in set features to work better — when these were put on the links, the browser kept reporting "1 of 1" all the time, not "1 of 3", "2 of 3", etc.

ARIA features used include:

New roles — `tablist`, `tab`, `tabpanel`

These identify the important areas of the tabbed interface — the container for the tabs, the tabs themselves, and the corresponding tabpanels.

`aria-selected`

Defines which tab is currently selected. As different tabs are selected by the user, the value of this attribute on the different tabs is updated via JavaScript.

`aria-hidden`

Hides an element from being read out by a screen reader. As different tabs are selected by the user, the value of this attribute on the different tabs is updated via JavaScript.

`tabindex="0"`

As we've removed the links, we need to give the list items this attribute to provide it with keyboard focus.

`aria-setsize`

This property allows you to specify to screen readers that an element is part of a series, and how many items the series has.

`aria-posinset`

This property allows you to specify what position in a series an element is in. Along with `aria-setsize`, it provides a screen reader with enough information to tell you that you are currently on item "1 of 3", etc. In many cases, browsers should be able to infer this information from the element hierarchy, but it certainly helps to provide more clues.

In our tests, this new structure did serve to improve things overall. The tabs are now recognized as tabs (e.g. "tab" is spoken by the screen reader), the selected tab is indicated by "selected" being read out with the tab name, and the screen reader also tells you which tab number you are currently on. In addition, because of the `aria-hidden` settings (only the non-hidden tab ever has `aria-hidden="false"` set), the non-hidden content is the only one you can navigate down to, meaning the selected content is easier to find.

**Note:** If there is anything you explicitly don't want screen readers to read out, you can give them the `aria-hidden="true"` attribute.

Test your skills!
-----------------

You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see Test your skills: WAI-ARIA.

Summary
-------

This article has by no means covered all that's available in WAI-ARIA, but it should have given you enough information to understand how to use it, and know some of the most common patterns you will encounter that require it.

See also
--------

* Aria states and properties: All `aria-*` attributes
* WAI-ARIA roles: Categories of ARIA roles and the roles covered on MDN
* ARIA in HTML on W3C: A specification that defines, for each HTML feature, the accessibility (ARIA) semantics implicitly applied on it by the browser and the WAI-ARIA features you may set on it if extra semantics are required
* Deque university code library: A library of really useful and practical examples showing complex UI controls made accessible using WAI-ARIA features
* WAI-ARIA authoring practices on W3C: A very detailed design pattern from the W3C, explaining how to implement different types of complex UI control whilst making them accessible using WAI-ARIA features
* Previous
* Overview: Accessibility
* Next


HTML: A good basis for accessibility - Learn web development

HTML: A good basis for accessibility
====================================

* Previous
* Overview: Accessibility
* Next

A great deal of web content can be made accessible just by making sure the correct Hypertext Markup Language elements are used for the correct purpose at all times. This article looks in detail at how HTML can be used to ensure maximum accessibility.

|  |  |
| --- | --- |
| Prerequisites: |
 A basic understanding of HTML (see
 Introduction to HTML), and an understanding of
 what accessibility is.
  |
| Objective: |
 To gain familiarity with the features of HTML that have accessibility
 benefits and how to use them appropriately in your web documents.
  |

HTML and accessibility
----------------------

As you learn more about HTML — read more resources, look at more examples, etc. — you'll keep seeing a common theme: the importance of using semantic HTML (sometimes called POSH, or Plain Old Semantic HTML). This means using the correct HTML elements for their intended purpose as much as possible.

You might wonder why this is so important. After all, you can use a combination of CSS and JavaScript to make just about any HTML element behave in whatever way you want. For example, a control button to play a video on your site could be marked up like this:

```html
<div>Play video</div>
```

But as you'll see in greater detail later on, it makes sense to use the correct element for the job:

```html
<button>Play video</button>
```

Not only do HTML `<button>`s have some suitable styling applied by default (which you will probably want to override), they also have built-in keyboard accessibility — users can navigate between buttons using the `Tab` key and activate their selection using `Space`, `Return` or `Enter`.

Semantic HTML doesn't take any longer to write than non-semantic (bad) markup if you do it consistently from the start of your project. Even better, semantic markup has other benefits beyond accessibility:

1. **Easier to develop with** — as mentioned above, you get some functionality for free, plus it is arguably easier to understand.
2. **Better on mobile** — semantic HTML is arguably lighter in file size than non-semantic spaghetti code, and easier to make responsive.
3. **Good for SEO** — search engines give more importance to keywords inside headings, links, etc. than keywords included in non-semantic `<div>`s, etc., so your documents will be more findable by customers.

Let's get on and look at accessible HTML in more detail.

**Note:** It is a good idea to have a screen reader set up on your local computer so that you can do some testing of the examples shown below. See our Screen readers guide for more details.

Good semantics
--------------

We've already talked about the importance of proper semantics, and why we should use the right HTML element for the job. This cannot be ignored, as it is one of the main places that accessibility is badly broken if not handled properly.

Out there on the web, the truth is that people do some very strange things with HTML markup. Some abuses of HTML are due to legacy practices that have not been completely forgotten, and some are just plain ignorance. Whatever the case, you should replace such bad code.

Sometimes you are not in the position to get rid of lousy markup — your pages might be generated by some kind of server-side framework over which you don't have full control, or you might have third party content on your page (such as ad banners) over which you have no control.

The goal isn't "all or nothing"; every improvement you can make will help the cause of accessibility.

### Text content

One of the best accessibility aids a screen reader user can have is an excellent content structure with headings, paragraphs, lists, etc. An excellent semantic example might look something like the following:

```html
<h1>My heading</h1>

<p>This is the first section of my document.</p>

<p>I'll add another paragraph here too.</p>

<ol>
  <li>Here is</li>
  <li>a list for</li>
  <li>you to read</li>
</ol>

<h2>My subheading</h2>

<p>
  This is the first subsection of my document. I'd love people to be able to
  find this content!
</p>

<h2>My 2nd subheading</h2>

<p>
  This is the second subsection of my content, which I think is more interesting
  than the last one.
</p>
```

We've prepared a version with longer text for you to try out with a screen reader (see good-semantics.html). If you try navigating through this, you'll see that this is pretty easy to navigate:

1. The screen reader reads each header out as you progress through the content, notifying you what a heading is, what is a paragraph, etc.
2. It stops after each element, letting you go at whatever pace is comfortable for you.
3. You can jump to the next/previous heading in many screen readers.
4. You can also bring up a list of all headings in many screen readers, allowing you to use them as a handy table of contents to find specific content.

People sometimes write headings, paragraphs, etc. using line breaks and adding HTML elements purely for styling, something like the following:

```html
<span style="font-size: 3em">My heading</span> <br /><br />
This is the first section of my document.
<br /><br />
I'll add another paragraph here too.
<br /><br />
1. Here is
<br /><br />
2. a list for
<br /><br />
3. you to read
<br /><br />
<span style="font-size: 2.5em">My subheading</span>
<br /><br />
This is the first subsection of my document. I'd love people to be able to find
this content!
<br /><br />
<span style="font-size: 2.5em">My 2nd subheading</span>
<br /><br />
This is the second subsection of my content. I think is more interesting than
the last one.
```

If you try our longer version out with a screen reader (see bad-semantics.html), you'll not have a very good experience — the screen reader hasn't got anything to use as signposts, so you can't retrieve a useful table of contents, and the whole page is seen as a single giant block, so it is just read out in one go, all at once.

There are other issues too beyond accessibility — it is harder to style the content using CSS, or manipulate it with JavaScript, for example, because there are no elements to use as selectors.

#### Using clear language

The language you use can also affect accessibility. In general, you should use clear language that is not overly complex and doesn't use unnecessary jargon or slang terms. This not only benefits people with cognitive or other disabilities; it benefits readers for whom the text is not written in their first language, younger people…, everyone, in fact! Apart from this, you should try to avoid using language and characters that don't get read out clearly by the screen reader. For example:

* Don't use dashes if you can avoid it. Instead of writing 5–7, write 5 to 7.
* Expand abbreviations — instead of writing Jan, write January.
* Expand acronyms, at least once or twice, then use the `<abbr>` tag to describe them.
### Page layouts

In the bad old days, people used to create page layouts using HTML tables — using different table cells to contain the header, footer, sidebar, main content column, etc. This is not a good idea because a screen reader will likely give out confusing readouts, especially if the layout is complex and has many nested tables.

Try our example table-layout.html example, which looks something like this:

```html
<table width="1200">
  <!-- main heading row -->
  <tr id="heading">
    <td colspan="6">
      <h1 align="center">Header</h1>
    </td>
  </tr>
  <!-- nav menu row -->
  <tr id="nav" bgcolor="#ffffff">
    <td width="200">
      <a href="#" align="center">Home</a>
    </td>
    <td width="200">
      <a href="#" align="center">Our team</a>
    </td>
    <td width="200">
      <a href="#" align="center">Projects</a>
    </td>
    <td width="200">
      <a href="#" align="center">Contact</a>
    </td>
    <td width="300">
      <form width="300">
        <label
 >Search
          <input
 type="search"
 name="q"
 placeholder="Search query"
 width="300" />
        </label>
      </form>
    </td>
    <td width="100">
      <button width="100">Go!</button>
    </td>
  </tr>
  <!-- spacer row -->
  <tr id="spacer" height="10">
    <td></td>
  </tr>
  <!-- main content and aside row -->
  <tr id="main">
    <td id="content" colspan="4">
      <!-- main content goes here -->
    </td>
    <td id="aside" colspan="2" valign="top">
      <h2>Related</h2>

      <!-- aside content goes here -->
    </td>
  </tr>
  <!-- spacer row -->
  <tr id="spacer" height="10">
    <td></td>
  </tr>
  <!-- footer row -->
  <tr id="footer">
    <td colspan="6">
      <p>©Copyright 1996 by nobody. All rights reversed.</p>
    </td>
  </tr>
</table>
```

If you try to navigate this using a screen reader, it will probably tell you that there's a table to be looked at (although some screen readers can guess the difference between table layouts and data tables). You'll then likely (depending on which screen reader you're using) have to go down into the table as an object and look at its features separately, then get out of the table again to carry on navigating the content.

Table layouts are a relic of the past — they made sense back when CSS support was not widespread in browsers, but now they just create confusion for screen reader users. Additionally, their source code requires more markup, which makes them less flexible and more difficult to maintain. You can verify these claims by comparing your previous experience with a more modern website structure example, which could look something like this:

```html
<header>
  <h1>Header</h1>
</header>

<nav>
  <!-- main navigation in here -->
</nav>

<!-- Here is our page's main content -->
<main>
  <!-- It contains an article -->
  <article>
    <h2>Article heading</h2>

    <!-- article content in here -->
  </article>

  <aside>
    <h2>Related</h2>

    <!-- aside content in here -->
  </aside>
</main>

<!-- And here is our main footer that is used across all the pages of our website -->

<footer>
  <!-- footer content in here -->
</footer>
```

If you try our more modern structure example with a screen reader, you'll see that the layout markup no longer gets in the way and confuses the content readout. It is also much leaner and smaller in terms of code size, which means easier to maintain code, and less bandwidth for the user to download (particularly prevalent for those on slow connections).

Another consideration when creating layouts is using HTML semantic elements as seen in the above example (see content sectioning) — you can create a layout using only nested `<div>` elements, but it is better to use appropriate sectioning elements to wrap your main navigation (`<nav>`), footer (`<footer>`), repeating content units (`<article>`), etc. These provide extra semantics for screen readers (and other tools) to give users extra clues about the content they are navigating (see Screen Reader Support for new HTML5 Section Elements for an idea of what screen reader support is like).

**Note:** In addition to having good semantics and an attractive layout, your content should make logical sense in its source order — you can always place it where you want using CSS later on, but you should get the source order right to start with, so what screen reader users get read out to them will make sense.

### UI controls

By UI controls, we mean the main parts of web documents that users interact with — most commonly buttons, links, and form controls. In this section, we'll look at the basic accessibility concerns to be aware of when creating such controls. Later articles on WAI-ARIA and multimedia will look at other aspects of UI accessibility.

One key aspect of the accessibility of UI controls is that by default, browsers allow them to be manipulated by the keyboard. You can try this out using our native-keyboard-accessibility.html example (see the source code). Open this in a new tab, and try pressing the tab key; after a few presses, you should see the tab focus start to move through the different focusable elements. The focused elements are given a highlighted default style in every browser (it differs slightly between different browsers) so that you can tell what element is focused.

![Three buttons with the text "Click me!", "Click me too!", and "And me!" inside them respectively. The third button has a blue outline around it to indicate current tab focus.](/en-US/docs/Learn/Accessibility/HTML/button-focused-unfocused.png)

**Note:** You can enable an overlay that shows the page tabbing order in your developer tools. For more information see: Accessibility Inspector > Show web page tabbing order.

You can then press Enter/Return to follow a focused link or press a button (we've included some JavaScript to make the buttons alert a message), or start typing to enter text in a text input. Other form elements have different controls; for example, the `<select>` element can have its options displayed and cycled between using the up and down arrow keys.

**Note:** Different browsers may have different keyboard control options available. See Using native keyboard accessibility for more details.

You essentially get this behavior for free, just by using the appropriate elements, e.g.

```html
<h1>Links</h1>

<p>This is a link to <a href="https://www.mozilla.org">Mozilla</a>.</p>

<p>
  Another link, to the
  <a href="https://developer.mozilla.org">Mozilla Developer Network</a>.
</p>

<h2>Buttons</h2>

<p>
  <button data-message="This is from the first button">Click me!</button>
  <button data-message="This is from the second button">Click me too!</button>
  <button data-message="This is from the third button">And me!</button>
</p>

<h2>Form</h2>

<form>
  <div>
    <label for="name">Fill in your name:</label>
    <input type="text" id="name" name="name" />
  </div>
  <div>
    <label for="age">Enter your age:</label>
    <input type="text" id="age" name="age" />
  </div>
  <div>
    <label for="mood">Choose your mood:</label>
    <select id="mood" name="mood">
      <option>Happy</option>
      <option>Sad</option>
      <option>Angry</option>
      <option>Worried</option>
    </select>
  </div>
</form>
```

This means using links, buttons, form elements, and labels appropriately (including the `<label>` element for form controls).

However, it is again the case that people sometimes do strange things with HTML. For example, you sometimes see buttons marked up using `<div>`s, for example:

```html
<div data-message="This is from the first button">Click me!</div>
<div data-message="This is from the second button">Click me too!</div>
<div data-message="This is from the third button">And me!</div>
```

But using such code is not advised — you immediately lose the native keyboard accessibility you would have had if you'd just used `<button>` elements, plus you don't get any of the default CSS styling that buttons get. In the rare to non-existent case when you need to use a non-button element for a button, use the `button` role and implement all the default button behaviors, including keyboard and mouse button support.

#### Building keyboard accessibility back in

Adding such advantages back in takes a bit of work (you can see an example in our fake-div-buttons.html example — also see the source code). Here we've given our fake `<div>` buttons the ability to be focused (including via tab) by giving each one the attribute `tabindex="0"`. We also include `role="button"` so screen reader users know they can focus on and interact with the element:

```html
<div data-message="This is from the first button" tabindex="0" role="button">
  Click me!
</div>
<div data-message="This is from the second button" tabindex="0" role="button">
  Click me too!
</div>
<div data-message="This is from the third button" tabindex="0" role="button">
  And me!
</div>
```

Basically, the `tabindex` attribute is primarily intended to allow tabbable elements to have a custom tab order (specified in positive numerical order), instead of just being tabbed through in their default source order. This is nearly always a bad idea, as it can cause major confusion. Use it only if you really need to, for example, if the layout shows things in a very different visual order to the source code, and you want to make things work more logically. There are two other options for `tabindex`:

* `tabindex="0"` — as indicated above, this value allows elements that are not normally tabbable to become tabbable. This is the most useful value of `tabindex`.
* `tabindex="-1"` — this allows not normally tabbable elements to receive focus programmatically, e.g., via JavaScript, or as the target of links.

While the above addition allows us to tab to the buttons, it does not allow us to activate them via the `Enter`/`Return` key. To do that, we had to add the following bit of JavaScript trickery:

```js
document.onkeydown = (e) => {
  // The Enter/Return key
  if (e.key === "Enter") {
    document.activeElement.click();
  }
};
```

Here we add a listener to the `document` object to detect when a button has been pressed on the keyboard. We check what button was pressed via the event object's `key` property; if the key pressed is `Enter`/`Return`, we run the function stored in the button's `onclick` handler using `document.activeElement.click()`. `activeElement` which gives us the element that is currently focused on the page.

This is a lot of extra hassle to build the functionality back in. And there's bound to be other problems with it. **Better to just use the right element for the right job in the first place.**

#### Meaningful text labels

UI control text labels are very useful to all users, but getting them right is particularly important to users with disabilities.

You should make sure that your button and link text labels are understandable and distinctive. Don't just use "Click here" for your labels, as screen reader users sometimes get up a list of buttons and form controls. The following screenshot shows our controls being listed by VoiceOver on Mac.

![List of form input labels being listed by VoiceOver software on Mac. This list contains meaningless labels like 'happy menu button` given to various form controls like button, textfield and link](/en-US/docs/Learn/Accessibility/HTML/voiceover-formcontrols.png)

Make sure your labels make sense out of context, read on their own, as well as in the context of the paragraph they are in. For example, the following shows an example of good link text:

```html
<p>
  Whales are really awesome creatures.
  <a href="whales.html">Find out more about whales</a>.
</p>
```

but this is bad link text:

```html
<p>
  Whales are really awesome creatures. To find out more about whales,
  <a href="whales.html">click here</a>.
</p>
```

**Note:** You can find a lot more about link implementation and best practices in our Creating hyperlinks article. You can also see some good and bad examples at good-links.html and bad-links.html.

Form labels are also important for giving you a clue about what you need to enter into each form input. The following seems like a reasonable enough example:

```html
Fill in your name: <input type="text" id="name" name="name" />
```

However, this is not so useful for disabled users. There is nothing in the above example to associate the label unambiguously with the form input and make it clear how to fill it in if you cannot see it. If you access this with some screen readers, you may only be given a description along the lines of "edit text."

The following is a much better example:

```html
<div>
  <label for="name">Fill in your name:</label>
  <input type="text" id="name" name="name" />
</div>
```

With code like this, the label will be clearly associated with the input; the description will be more like "Fill in your name: edit text."

![A good form label that reads 'Fill in your name' is given to a text input form control. ](/en-US/docs/Learn/Accessibility/HTML/voiceover-good-form-label.png)

As an added bonus, in most browsers associating a label with a form input means that you can click the label to select or activate the form element. This gives the input a bigger hit area, making it easier to select.

**Note:** You can see some good and bad form examples in good-form.html and bad-form.html.

You can find a nice explanation of the importance of proper text labels, and how to investigate text label issues using the Firefox Accessibility Inspector, in the following video:

Accessible data tables
----------------------

A basic data table can be written with very simple markup, for example:

```html
<table>
  <tr>
    <td>Name</td>
    <td>Age</td>
    <td>Pronouns</td>
  </tr>
  <tr>
    <td>Gabriel</td>
    <td>13</td>
    <td>he/him</td>
  </tr>
  <tr>
    <td>Elva</td>
    <td>8</td>
    <td>she/her</td>
  </tr>
  <tr>
    <td>Freida</td>
    <td>5</td>
    <td>she/her</td>
  </tr>
</table>
```

But this has problems — there is no way for a screen reader user to associate rows or columns together as groupings of data. To do this, you need to know what the header rows are and if they are heading up rows, columns, etc. This can only be done visually for the above table (see bad-table.html and try the example out yourself).

Now have a look at our punk bands table example — you can see a few accessibility aids at work here:

* Table headers are defined using `<th>` elements — you can also specify if they are headers for rows or columns using the `scope` attribute. This gives you complete groups of data that can be consumed by screen readers as single units.
* The `<caption>` element and the `<table>` element's `summary` attribute both do similar jobs — they act as alt text for a table, giving a screen reader user a useful quick summary of the table's contents. The `<caption>` element is generally preferred as it makes it's content accessible to sighted users too, who might also find it useful. You don't really need both.

**Note:** See our HTML table advanced features and accessibility article for more details about accessible data tables.

Text alternatives
-----------------

Whereas textual content is inherently accessible, the same cannot necessarily be said for multimedia content — image and video content cannot be seen by visually-impaired people, and audio content cannot be heard by hearing-impaired people. We cover video and audio content in detail in the Accessible multimedia, but for this article we'll look at accessibility for the humble `<img>` element.

We have a simple example written up, accessible-image.html, which features four copies of the same image:

```html
<img src="dinosaur.png" />

<img
 src="dinosaur.png"
 alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth." />

<img
 src="dinosaur.png"
 alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth."
 title="The Mozilla red dinosaur" />

<img src="dinosaur.png" aria-labelledby="dino-label" />

<p id="dino-label">
  The Mozilla red Tyrannosaurus Rex: A two legged dinosaur standing upright like
  a human, with small arms, and a large head with lots of sharp teeth.
</p>
```

The first image, when viewed by a screen reader, doesn't really offer the user much help — VoiceOver for example reads out "/dinosaur.png, image". It reads out the filename to try to provide some help. In this example the user will at least know it is a dinosaur of some kind, but often files may be uploaded with machine-generated file names (e.g. from a digital camera) and these file names would likely provide no context to the image's content.

**Note:** This is why you should never include text content inside an image — screen readers can't access it. There are other disadvantages too — you can't select it and copy/paste it. Just don't do it!

When a screen reader encounters the second image, it reads out the full alt attribute — "A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth.".

This highlights the importance of not only using meaningful file names in case so-called **alt text** is not available, but also making sure that alt text is provided in `alt` attributes wherever possible.

Note that the contents of the `alt` attribute should always provide a direct representation of the image and what it conveys visually. The alt should be brief and concise and include all the information conveyed in the image that is not duplicated in the surrounding text.

The content of the `alt` attribute for a single image differs based on the context. For example, if the photo of Fluffy is an avatar next to a review for Yuckymeat dog food, `alt="Fluffy"` is appropriate. If the photo is part of Fluffy's adoption page for the animal rescue society, information conveyed in the image that is relevant for a prospective dog parent that is not duplicated in the surrounding text should be included. A longer description, such as `alt="Fluffy, a tri-color terrier with very short hair, with a tennis ball in her mouth."` is appropriate. As the surrounding text likely has Fluffy's size and breed, that is not included in the `alt`. However, as the dog's biography likely doesn't include hair length, colors, or toy preferences, which the potential parent needs to know, it is included. Is the image outdoors, or does Fluffy have a red collar with a blue leash? Not important in terms of adopting the pet and therefore not included. All information image conveys that a sited user can access and is relevant to the context is what needs to be conveyed; nothing more. Keep it short, precise, and useful.

Any personal knowledge or extra description shouldn't be included here, as it is not useful for people who have not seen the image before. If the ball is Fluffy's favorite toy or if the sited user can't know that from the image, then don't include it.

One thing to consider is whether your images have meaning inside your content, or whether they are purely for visual decoration, and thus have no meaning. If they are decorative, it is better to write an empty text as a value for `alt` attribute (see Empty alt attributes) or to just include them in the page as CSS background images.

**Note:** Read Images in HTML and Responsive images for a lot more information about image implementation and best practices.

If you do want to provide extra contextual information, you should put it in the text surrounding the image, or inside a `title` attribute, as shown above. In this case, most screen readers will read out the alt text, the title attribute, and the filename. In addition, browsers display title text as tooltips when moused over.

![Screenshot of a red Tyrannosaurus Rex with the text "The mozilla red dinosaur" displayed as tooltip on mouseover.](/en-US/docs/Learn/Accessibility/HTML/title-attribute.png)

Let's have another quick look at the fourth method:

```html
<img src="dinosaur.png" aria-labelledby="dino-label" />

<p id="dino-label">The Mozilla red Tyrannosaurus…</p>
```

In this case, we are not using the `alt` attribute at all — instead, we have presented our description of the image as a regular text paragraph, given it an `id`, and then used the `aria-labelledby` attribute to refer to that `id`, which causes screen readers to use that paragraph as the alt text/label for that image. This is especially useful if you want to use the same text as a label for multiple images — something that isn't possible with `alt`.

**Note:** `aria-labelledby` is part of the WAI-ARIA spec, which allows developers to add in extra semantics to their markup to improve screen reader accessibility where needed. To learn more about how it works, read our WAI-ARIA Basics article.

### Figures and figure captions

HTML includes two elements — `<figure>` and `<figcaption>` — which associate a figure of some kind (it could be anything, not necessarily an image) with a figure caption:

```html
<figure>
  <img
 src="dinosaur.png"
 alt="The Mozilla Tyrannosaurus"
 aria-describedby="dinodescr" />
  <figcaption id="dinodescr">
    A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a
    human, with small arms, and a large head with lots of sharp teeth.
  </figcaption>
</figure>
```

While there is mixed screen reader support of associating figure captions with their figures, including `aria-labelledby` or `aria-describedby` creates the association if none is present. That said, the element structure is useful for CSS styling, plus it provides a way to place a description of the image next to it in the source.

### Empty alt attributes

```html
<h3>
  <img src="article-icon.png" alt="" />
  Tyrannosaurus Rex: the king of the dinosaurs
</h3>
```

There may be times where an image is included in a page's design, but its primary purpose is for visual decoration. You'll notice in the code example above that the image's `alt` attribute is empty — this is to make screen readers recognize the image, but not attempt to describe the image (instead they'd just say "image", or similar).

The reason to use an empty `alt` instead of not including it is because many screen readers announce the whole image URL if no `alt` is provided. In the above example, the image is acting as a visual decoration to the heading it's associated with. In cases like this, and in cases where an image is only decoration and has no content value, you should include an empty `alt` in your `img` elements. Another alternative is to use the aria `role` attribute `role="presentation"` as this also stops screen readers from reading out alternative text.

**Note:** If possible you should use CSS to display images that are only decorative.

More on links
-------------

Links (the `<a>` element with an `href` attribute), depending on how they are used, can help or harm accessibility. By default, links are accessible in appearance. They can improve accessibility by helping a user quickly navigate to different sections of a document. They can also harm accessibility if their accessible styling is removed or if JavaScript causes them to behave in unexpected ways.

### Link styling

By default, links are visually different from other text in both color and text-decoration, with links being blue and underlined by default, purple and underlined if visited, and with a focus-ring when they receive keyboard focus.

Color should not be used as the sole method of distinguishing links from non-linking content. Link text color, like all text, has to be significantly different from the background color (a 4.5:1 contrast). In addition, links should visually be significantly different from non-linking text, with a minimum contrast requirement of 3:1 between link text and surrounding text and between default, visited, and focus/active states and a 4.5:1 contrast between all those state colors and the background color.

### `onclick` events

Anchor tags are often abused with the `onclick` event to create pseudo-buttons by setting **href** to `"#"` or `"javascript:void(0)"` to prevent the page from refreshing.

These values cause unexpected behavior when copying or dragging links, opening links in a new tab or window, bookmarking, and when JavaScript is still downloading, errors out, or is disabled. This also conveys incorrect semantics to assistive technologies (e.g., screen readers). In these cases, it is recommended to use a `<button>` instead. In general you should only use an anchor for navigation using a proper URL.

### External links and linking to non-HTML resources

Links that open in a new tab or window via the `target="_blank"` declaration and links to whose `href` value points to a file resource should include an indicator about the behavior that will occur when the link is activated.

People experiencing low vision conditions, who are navigating with the aid of screen reading technology, or who have cognitive concerns may become confused when the new tab, window, or application is opened unexpectedly. Older versions of screen reading software may not even announce the behavior.

#### Link that opens a new tab or window

```html
<a target="\_blank" href="https://www.wikipedia.org/"
 >Wikipedia (opens in a new window)</a
>
```

#### Link to a non-HTML resource

```html
<a target="\_blank" href="2017-annual-report.ppt"
 >2017 Annual Report (PowerPoint)</a
>
```

If an icon is used in place of text to signify this kind of links behavior, make sure it includes an alternate description.

* WebAIM: Links and Hypertext - Hypertext Links
* MDN Understanding WCAG, Guideline 3.2 explanations
* G200: Opening new windows and tabs from a link only when necessary | W3C Techniques for WCAG 2.0
* G201: Giving users advanced warning when opening a new window | W3C Techniques for WCAG 2.0
### Skip links

A skip link, also known as skipnav, is an `a` element placed as close as possible to the opening `<body>` element that links to the beginning of the page's main content. This link allows people to bypass content repeated throughout multiple pages on a website, such as a website's header and primary navigation.

Skip links are especially useful for people who navigate with the aid of assistive technology such as switch control, voice command, or mouth sticks/head wands, where the act of moving through repetitive links can be a laborious task.

* WebAIM: "Skip Navigation" Links
* How–to: Use Skip Navigation links - The A11Y Project
* MDN Understanding WCAG, Guideline 2.4 explanations
* Understanding Success Criterion 2.4.1 | W3C Understanding WCAG 2.0
### Proximity

Large amounts of interactive content—including anchors—placed in close visual proximity to each other should have space inserted to separate them. This spacing is beneficial for people who suffer from fine motor control issues and may accidentally activate the wrong interactive content while navigating.

Spacing may be created using CSS properties such as `margin`.

* Hand tremors and the giant-button-problem - Axess Lab
Test your skills!
-----------------

You've reached the end of this article, but can you remember the most important information? See Test your skills: HTML Accessibility to verify that you've retained this information before you move on.

Summary
-------

You should now be well-versed in writing accessible HTML for most occasions. Our WAI-ARIA basics article will help to fill gaps in this knowledge, but this article has taken care of the basics. Next up we'll explore CSS and JavaScript, and how accessibility is affected by their good or bad use.

* Previous
* Overview: Accessibility
* Next


Test your skills: HTML accessibility - Learn web development

Test your skills: HTML accessibility
====================================

The aim of this skill test is to assess whether you've understood our HTML: A good basis for accessibility article.

**Note:** You can try solutions in the interactive editors on this page or in an online editor such as CodePen, JSFiddle, or Glitch.

If you get stuck, you can reach out to us in one of our communication channels.

HTML accessibility 1
--------------------

In this task we will test your understanding of text semantics, and why they are good for accessibility. The given text is a simple information panel with action buttons, but the HTML is really bad.

We want you to update it use appropriate semantic HTML. You don't need to worry too much about recreating the *exact* same look and text sizing, as long as the semantics are good.

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

HTML accessibility 2
--------------------

In the second task, you have a form containing three input fields. You need to:

* Semantically associate the input with their labels.
* Assume that these inputs will be part of a larger form, and wrap them in an element that associates them all together as a single related group.
* Give the group a description/title that summarizes all of the information as personal data.

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

HTML accessibility 3
--------------------

In this task you are required to turn all the information links in the paragraph into good, accessible links.

* The first two links just go to regular web pages.
* The third link goes to a PDF, and it's large — 8MB.
* The fourth link goes to a Word document, so the user will need some kind of application installed that can handle that.

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.

HTML accessibility 4
--------------------

In our final HTML accessibility task, you are given a simple image gallery, which has some accessibility problems. Can you fix them?

* The header image has an accessibility issue, and so do the gallery images.
* You could take the header image further and implement it using CSS for arguably better accessibility. Why is this better, and what would a solution look like?

Try updating the live code below to recreate the finished example:

Download the starting point for this task to work in your own editor or in an online editor.