tabindex
Controls whether and in what order an element can receive keyboard focus. Essential for custom widgets, focus management, and accessible single-page applications.
Overview
The tabindex attribute controls whether an element can receive keyboard focus and where it sits in the sequential tab order. It is a global attribute — it can be placed on any HTML element.
Interactive elements like <button>, <a href>, <input>, <select>, and <textarea> are already focusable without tabindex. You only need this attribute when working with non-interactive elements or managing focus programmatically.
Values
| Value | Behavior | When to Use |
|---|---|---|
0 |
Element is focusable and included in the natural tab order (based on DOM position) | Custom interactive widgets built from non-interactive elements |
-1 |
Element is focusable via JavaScript (element.focus()) but excluded from the tab order |
Focus management targets: modals, headings after route changes, error summaries |
1+ (positive) |
Element is focusable and placed before all tabindex="0" elements in tab order |
Avoid. Breaks the natural document order and creates maintenance nightmares. |
Why Avoid Positive Values
Positive tabindex values (1, 2, 3, etc.) force elements to the front of the tab order, regardless of their position in the document. This creates several problems:
- Unpredictable navigation: Focus jumps around the page instead of following the visual flow
- Maintenance burden: Every new focusable element requires re-numbering to maintain order
- Conflicts at scale: Third-party widgets and your own code compete for tab positions
- Confusing for all users: Sighted keyboard users and screen reader users alike expect Tab to follow visual order
Instead of adjusting tabindex values, reorder elements in the DOM to match the desired focus sequence.
Native Focusability
These elements are focusable by default and do not need tabindex:
<button><a href="...">(links with anhref)<input>,<select>,<textarea><details>(via its<summary>)- Elements with
contenteditable
Adding tabindex="0" to these elements is harmless but redundant. Adding tabindex="-1" to them removes them from the tab order while keeping them programmatically focusable — useful for temporarily disabling keyboard access without using disabled.
Common Patterns
Skip Links
A skip link lets keyboard users bypass navigation and jump to the main content. The target needs tabindex="-1" so the skip link can move focus to it.
Focus After Action
When an action removes the currently focused element (deleting a list item, closing a panel), focus must be moved somewhere logical. Use tabindex="-1" on the target and call .focus().
SPA Route Changes
In single-page applications, after a client-side navigation the browser does not move focus. Add tabindex="-1" to the new page heading and focus it after the route change so screen reader users know the page has changed.
Custom Widgets
When building custom interactive components from non-interactive elements, tabindex="0" makes the element reachable via Tab. Always pair it with the appropriate ARIA role and keyboard event handlers.
Roving Tabindex
For composite widgets like toolbars, tab lists, and menus, the roving tabindex pattern allows only one child to be in the tab order at a time. Arrow keys move focus between children.
This pattern keeps the Tab key for moving between widgets while arrow keys navigate within a widget — matching the behavior users expect from native controls.
Accessibility
- Prefer native interactive elements. A
<button>is always better than a<div tabindex="0" role="button">. Native elements provide keyboard interaction, focus styling, and screen reader announcements for free. - If you add
tabindex="0", add a role. Screen readers need an ARIA role to announce what the element is. A focusable<div>without a role is announced as "group" — meaningless to users. - If you add
tabindex="0", add keyboard handlers. Focusable elements must respond to Enter and (for buttons) Space. Click handlers alone are not enough. - Manage focus intentionally. When content changes (modals open, items are deleted, routes change), always move focus to a logical location.
- Visible focus styles are required. VB provides default
:focus-visibleoutlines. Never remove them without providing an alternative. - Test with keyboard only. Put the mouse away and Tab through the page. If you can't reach or operate every interactive element, something is missing.
See Also
hidden— remove elements from rendering and focus order entirely- Accessibility Guide — overview of VB's accessibility patterns
popover— overlay content with built-in focus management<button>— the preferred element for interactive controls<dialog>— modal dialogs with automatic focus trapping