What's The Deal With tabindex="0"?

Form Structure

HTML forms are generally comprised of a number of <input>s and <label>s along with a submit <button> at the end. But every now and again a non-form element appears within a form. We will deal with that in this article.

Screen Readers

Background

A unique challenge that forms present to us as web developers is that blind users interact with computers very differently than sighted users. Sighted users navigate pages through sight. Lots of information is presented at once, and the user determines what information to focus on at a time. Hopefully, before going from one page to another, the user will have focused on, and taken in, all relavent information on the page.

Blind users, however, must consume a page in a very different manner. They don't navigate by sight. They navigate by way of special keys in their screen reader. (Ex: "h" takes you to the next <h#> heading, "t" takes you to the next <table>.)

Once a screen reader user lands in a form element, the screen reader changes behavior; it enters "forms mode." Now, instead of "t" taking you to the next <table>, it enters a "T" in the <input>.

So, how does a blind user interact with a <form> in "forms mode"? There are two primary ways of doing this. The main way is to go from <input> to <input> via the Tab key. The other way is to use the Esc key to exit "forms mode" and continue to navigate the page in the usual way.

(It is my personal opinion that once a user has started filling out a form, why would a user exit "forms mode" just to go to the next <input> when Tab would do the job? A user may have a reason, but I think it's probably safe to assume that the majority would just use Tab. Even if some done, we need to code for those who do.)

To recap: A screen reader in "forms mode" will read the following HTML elements:

It is safe to assume that once a blind user hits the first form element, they will stay in "forms mode" until they get to the Submit <button>. (If that assumption is incorrect, but we code for it anyway, we hit all scenarios.)

The problem

A problem arises in the situation where a form has some extra information or instructions that comes after the first <input> that's not in one of the above elements. A blind user will just Tab right over it and miss it completely.

We will use the following form as an example:

Possible Solutions

Ideally, all instructions for a form should come before the form begins. However, sometimes that not practical or possible. (Most forms on the web are small and simple. But in a corporate environment, (esp. a government site) forms can be long and complex.)

There are a few ways to solve this problem: aria-, tabindex="0", <details>/<summary>, overlays, <textarea readonly>. Each has its own pros and cons. We will consider them each here.

aria-

ARIA stands for Accessible Rich Internet Applications. Aria- is a set of attributes that can be used in HTML elements to increase the accessibility of the web page. Aria- is to be used where HTML currently lacks. There's a common saying amongst accessibility professionals that goes The first rule of Aria is: Don't use Aria.. That means: if there's a way to do something with native HTML, do it that way.

For example, don't do this:

				
		<span id="myLabel">Enter your username</span>
		<input id="username" aria-labelledby="myLabel">
				
				

When you could do this:

				
		<label for="username">Enter your username</label>
		<input id="username">
		
				

The two Aria- attributes that we're concerned with here are aria-labelledby and aria-describedby. aria-labelledby can be used when an element doesn't have a native <label>. An element may only have one aria-labelledby value.

aria-describedby is used to add extra information to an element; more than a <label>. aria-describedby uses a space-separated list of id values. It's perfect for extra information aside from what's in the <label>. For example:

				
		<label for="username">Enter your username</label>
		<span id="usernameExplanation">This is the username you used to register.</span>
		<input id="username" aria-describedby="usernameExplanation">
				
				

It can even be used for adding error messages. (Note the space deliminited list of id values in aria-describedby.)

				
		<label for="username">Enter your username</label>
		<span id="usernameExplanation">This is the username you used to register.</span>
		<input id="username" aria-describedby="usernameExplanation usernameError">
		<span id="usernameError">I'm sorry but that username isn't valid for some reason.</span>
				
				
Advantages

It's clean and it's proper.

Disadvatanges

The main limitation with anything Aria- is support. Browsers and AT (assistive technologies) don't support all Aria- attributes in a consistent way. Support for aria-describedby on <input>s is pretty good, support for aria-describedby on just about everything else is pretty bad or non-existant. At the very least, it's inconsistent.

tabindex="0"

Another way to present non-form information in a form is to make it focusable by using tabindex="0". Example:

				
		<label for="password1">Enter a password</label>
		<input type="password1" id="password1">
		<p tabindex="0">Passwords must have at least one uppercase letter, one lowercase character, one numeric digit, be at least 8 characters.</p>
		<p tabindex="0">Both passwords must match.</p>
		<label for="password2">Re-enter password</label>
		<input type="password2" id="password1">
				
				

In the above example, a user would tab to the first password field, hit Tab, and the first paragraph would be focused (and read by a screen reader), then the second paragraph, and then the second password field.

Advantages

The best things about tabindex="0" are that it's simple to implement and widely supported (i.e.: all major desktop browsers).

Disadvantages

The biggest disadvantage of using tabindex="0" is that it's a usability problem for keyboard users. When you tab to something, you expect that something to be interactive. But simply adding tabindex="0" to a <p> tag makes it focusable, but non-interactive. This can be confusing. I have seen it described (by a blind person) as "Horrible Ux".

Another disadvantage is for sighted-keyboard-only users. They have to tab through all this stuff they can see (all the time wondering if the thing they're focused on is interactive, and if so, how to interact with it) just to get to the actual interactive parts.

Sometimes when a developer is told "This one section will be missed by screen reader users in forms mode. Add tabindex='0' to fix," they hear: Tabindex='0' All the things! and they put it in almost every HTML element.

Another disadvantage is that using the "Next" button while filling out a form in iOS will skip over non-form elements, even if it has tabindex="0". (However, it's fair to mention that blind mobile users interact with their devices completely differently than they do with desktop devices. So it's an apples and oranges comparison.)

Details/Summary

The <details>/<summary> tags can be used when implemented properly. When supported, <summary> tags are naturally focusable. A user would Tab to it, hit Enter and/or Space to expand, and use the down arrow key to read the contents.

Advantages

It's native HTML5, and the contents can be hidden or expanded at will.

Disadvantages

Not all browsers support <details>/<summary>, so polyfills would have to be created for those that don't. (These polyfills are included in Web Experience Toolkit (WET).)

Worse yet, they're relatively new and not entirely supported, and they don't do well in user experience testing. Sometimes you use Enter and sometimes you use Space. It's inconsistent.

Overlays

Overlays can be kind of like a pop-up. You see them a lot when you read an article someone posted on Facebook and after the article loads a box shows up asking to send every article on that site to your Inbox.

Examples can be seen on a Web Experience Toolkit (WET) demo page.

Overlays are good for extra help on a form field that doesn't need to be displayed all the time (and may never be displayed).

Advantages

They do better in user experience testing than <details>/<summary>s. Since they're pretty common, users generally know how to use them.

Disadvantages

Unless you're using WET on your site, they're not native HTML, so they can be hard to properly implement. Some sites always position them a relative number of pixels from the top-left corner of the viewing area. This is a problem for mobile users because they may never be able to bring the close button into the viewing area, so they can't close the overlay.

Also, if not implemented properly, they can wreak havok with keyboard tabbing. You may be able to tab out of an overlay without it closing. Or, you may accidentally create a keyboard trap.

A Readonly <textarea>

Some suggest if you have a lot of information, why not put it in a <textarea readonly>? This would make it focusable and readable, but not updateable.

Advantages

It's simple and it uses native well-supported HTML. You could even use CSS to make the borders disappear, or look any way you want. No polyfills are required.

Disadvantages

It's a hack. It's Not's not semantically correct. A <textarea> is for the user to enter or edit a large amount of data to be sumbitted as part of the form.

Unless the <textarea> has a form attribute in it to point to a different form, then the contents of that <textarea> will be sent to the server. It's not clean, it's not efficient, and it's not semantically correct (which is a WCAG 1.3.1 - Info and Relationships issue).

Which Should I Use?

Which solution should you use when you must have non-form information inside a form? While each situation is unique, here are some guidelines to help you decide.

Use tabindex="0" When:

Use aria-describedby When:

Use <details>/<summary>s When:

Use Overlays When:

Use A Readonly <textarea> When: