✎ Technique: Focus order and tabindex

Interactive elements should, under most circumstances, be focusable in the order that they appear in the source code. This helps people who are using the keyboard or alternative input devices to follow focus in a logical order.

The order that elements appear in the document source should reflect the order they appear visually.


Bad example

The tabindex attribute can adjust the natural focus order of interactive elements like buttons and form inputs. For instance, tabindex="1" lets you make an element the first element focusable within a page, irrespective of where it appears in the source. However, this disrupts the page’s intuitive focus order. In the following example, the third button will receive focus first, then—because the first and second buttons have no positive tabindex value set—the first button will be focused next:

<button>first button</button> 
<button>second button</button>
<button tabindex="1">third button</button>

The only way to guarantee that an interactive element receives focus after the "third button" element would be to give it tabindex="2", and then give the next element tabindex="3", and so on, incrementing the tabindex value for each successive element. This can become unmaintainable very quickly, especially when the page is likely to accumulate new active elements over time.

Good example

For buttons, links and other interactive elements that are natively focusable, the best strategy is to avoid using the tabindex attribute altogether. In the following example, the first button is focused first and then after that, the third button is focused. The reason the second button is not in the focus order is because it is disabled (through the disabled attribute).

<button>first button</button> 
<button disabled>second button</button>
<button>third button</button>

Custom button example

The tabindex attribute is helpful for focus management in some cases, however. 

When making custom interactive elements (as one would when constructing a web component), they don't always automatically have traits like focusability built into them. You have to provide these manually. To make a custom element focusable like a <button> is, you must supply it with a tabindex value of 0:

<my-button role="button" tabindex="0">first button</my-button> 
<my-button role="button" tabindex="0">second button</my-button> 
<my-button role="button" tabindex="0">third button</my-button>

In the above code example, the custom <my-button> elements will be focused logically from first to third.

Disabling with tabindex="-1"

Custom elements do not support the disabled attribute, which would normally make them unfocusable (as in the second example). To simulate this behavior, you can give the element a tabindex value of -1.

<my-button role="button" tabindex="0">first button</my-button> 
<my-button role="button" tabindex="-1">second button</my-button> 
<my-button role="button" tabindex="0">third button</my-button>

In the above code example, the second button is not focusable. So focus moves directly from the first button to the third. To make sure that the simulated disabled styles for custom elements are in keeping with the disabled styles of standard buttons, you can use attribute selectors in your CSS:

button[disabled], [role="button"][tabindex="-1"] {
  opacity: 0.6; /* fade the element out, to reduce its visual affordance */

Code editor

Test the tabindex values in the preceding examples using this code editor. Be sure to experiment by changing and removing the tabindex attributes before and then use your TAB key to switch focus between the elements.

See the Pen test tabindex values by HUIT - Web, UX and Digital Accessibility Services (@hwpdas) on CodePen.