How and when to use the tabindex attribute
tabindex
is a global attribute that can be applied to most HTML elements with content. It controls two things:
- If an element is focusable, either by an input method such as the keyboard, or programatically such as with the
focus()
method; and - At what point an element becomes focusable when a user is interacting with the page via a keyboard
Focus order #
To understand how the tabindex
attribute works, we first need to understand how focus is controlled on a page.
There are six 1 HTML elements which, by default, are focusable:
<a>
elements with anhref
attribute<link>
elements with anhref
attribute<button>
elements<input>
elements that are nottype="hidden"
<select>
elements<textarea>
elements
By default, only these elements can be brought into focus either with a user tabbing around the page with a keyboard or via the focus()
method in Javascript.
document.querySelector("a").focus();
Without any intervention, calling focus()
on any other element simply will not work.
document.querySelector("div").focus();
Will not work
The order in which these elements are placed in the source HTML document controls the order in which they become focusable when navigating with a keyboard.
Although this default behaviour covers most of the interaction we would need, there may be cases where we want to remove, add, or re-arrange items in the focus order. This is where the tabindex
attribute becomes handy.
How to use tabindex
#
The tabindex
attribute can be applied to almost any element, whether it is by default focusable or not. The value of the attribute must be a valid integer and can either be negative, positive, or exactly zero.
Negative tabindex
values #
A negative tabindex
, for example -1
, will omit the element from the focus order entirely. A user navigating the page using a keyboard will not be able to access the element at all.
<button type="button">Click me to start, then press the "tab" key</button>
<button type="button">I’ll be in focus first</button>
<button type="button" tabindex="-1">I won’t be in focus :(</button>
<button type="button">I’ll be in focus last</button>
The exact negative value chosen doesn’t actually matter. Since any negative value will remove the element from focus, there is no difference if the value is -1
or -99999
. Therefore, for readability and consistency, it is best to stick with -1
.
A tabindex
value of zero #
A tabindex
equals to exactly zero will place the element in the default focus order, determined by its position in the source HTML. It can be applied to elements that are not typically focusable, and will add them to the natural focus order as if they were.
<button type="button">Click me to start, then press the "tab" key</button>
<button type="button">I’ll be in focus first</button>
<div tabindex="0">I’m a DIV and will be in focus second</div>
<button type="button">I’ll be in focus last</button>
Positive tabindex
values #
Finally, a positive tabindex
will place the element in the focus order, but it’s position will be determined by the specific number, starting from 1 and going up. Elements with a positive tabindex
will also be placed in front of elements that don’t have a tabindex
attribute.
<button type="button" tabindex="1">I’m the first focusable item on the page</button>
<button type="button" tabindex="500">I’m the second</button>
To test this out, click on the URL bar of your browser, then hit tab. You'll see that the first two focusable items on this page are the buttons below, even though they are in the middle of the source HTML.
Programmatic focus and tabindex
#
Besides controlling which elements can be focusable via the keyboard and focus order, the tabindex
attribute also controls which elements can be focusable via Javascript.
Adding the tabindex
attribute to an element, regardless of the value, makes it focusable via Javascript. This means that we can make elements that are previously unfocusable to be focusable via Javascript, without also making them able to be focused via the user tabbing around using their keyboard.
Let’s take this <div>
, for example, with a negative tabindex
.
<div tabindex="-1">I'm a div</div>
If we were to navigate using the keyboard, we will see that it is not able to grab focus.
However, we can bring focus to it using the focus()
method.
<button type="button"
onclick="document.getElementById('demo-div').focus();">
Click me to focus the DIV
</button>
<div id="demo-div" tabindex="-1">I'm a div</div>
Next, we’ll see how this difference between tab and programmatic focus makes the tabindex
attribute useful.
When to use tabindex
#
The tabindex
attribute can be very useful, but has potentially destructive consequences if not used correctly. Each category of tabindex
value should be used in different circumstances.
When to use a negative tabindex
value #
As we have covered, a negative tabindex
value will remove the element from tab focus, but can add elements to programmatic focus.
A great example of when this is useful is modals. Modal containers are typically unfocusable elements like <div>
or <section>
. When a modal window is open, we may want to move focus to it so that screen readers will read out its content. But, we don’t want the modal container itself to be able to receive tab focus. This can be achieved using a negative tabindex
.
<div id="modal" tabindex="-1">
<!-- Modal content -->
</div>
<script>
function openModal() {
document.getElementById("modal").focus();
// Other stuff to show modal
}
</script>
When to use a tabindex
value of zero #
A tabindex
of zero is typically used either to add focus back to elements that it was programatically removed from.
Another good use case for this value is for custom elements. For example, we may need to create a custom button element, which will not be focusable by default because it's not actually a <button>
. We can add this functionality back with the tabindex
attribute, and specify its focus order as any regular button
element would have.
<my-custom-button tabindex="0">Click me!</my-custom-button>
When to use a positive tabindex
value #
There is almost no reason to ever use a positive value to tabindex
, and it is actually considered an anti-pattern. If you’re finding the need to use this value to change the order in which elements become focusable, it is likely that what you actually need to do is change the source order of the HTML elements.
#1 - I excluded the menuitem
element as it’s no longer valid HTML