WCAG's Operable principle requires every piece of functionality to work via keyboard alone. This lesson covers how tab order is computed, how to use tabindex correctly, and the key conventions expected from custom interactive widgets.
1How Tab Order Is Computed
The browser builds its default tab order by walking the DOM and collecting every naturally focusable element (links with href, buttons, form controls, and any element with tabindex="0" or higher) in source order.
This has a critical implication: visual reordering via CSS (order in flexbox/grid, position: absolute) does not change tab order. If a design team reorders a form's columns visually without updating the underlying markup order, keyboard users experience a tab sequence that jumps illogically around the screen, even though it looks fine to sighted mouse users.
2Using tabindex Correctly
tabindex="0" is the only value that safely inserts a non-natively-focusable element (like a custom <div role="button">, when a native button genuinely can't be used) into the natural tab sequence at its DOM position.
tabindex="-1" removes an element from Tab-key navigation entirely while still allowing it to receive focus programmatically via element.focus() in JavaScript ā the standard technique for moving focus into a newly-opened dialog or after a route change in a single-page app.
Positive tabindex values (1, 2, 3...) create an explicit override order that takes priority over all tabindex="0" elements, fragmenting the natural flow. It is universally discouraged in modern accessibility guidance because it becomes unmaintainable as a page grows.
3Reimplementing Native Key Conventions
Native elements come bundled with expected key behavior: checkboxes and buttons activate with Space, links and buttons activate with Enter, <select> opens and navigates with arrow keys. Users have learned these conventions across the entire web.
When a team builds a custom widget ā a tab list, a combobox, a menu, a slider ā from generic elements, they take on responsibility for reimplementing the matching key conventions defined in the W3C ARIA Authoring Practices Guide (APG). Skipping this step is the single most common way ARIA-enhanced widgets fail real-world keyboard testing, even when their roles and labels are technically correct.
4Step-by-Step Breakdown
If It Can't Be Tabbed To, It Doesn't Exist. Many users, not only those with motor impairments, navigate entirely by keyboard: power users, screen reader users, and anyone with a broken trackpad. WCAG 2.1.1 Keyboard requires that all functionality be operable through a keyboard interface, with no exceptions for 'it's easier with a mouse.'
Tab Order Follows DOM Order. By default, pressing Tab moves focus through focusable elements in the order they appear in the DOM, not their visual CSS position. When CSS reorders elements visually (flexbox order, absolute positioning) without a matching DOM reorder, tab order can feel illogical.
Tab Order Source. A form's fields are visually reordered with CSS flexbox order, but the tab order still follows the original markup sequence. Why?
- āThis is always a browser rendering bug
- āDefault tab order follows DOM order, which CSS visual reordering doesn't change
- āTab order is effectively randomized by the browser
tabindex: Use 0 And -1, Avoid Positive Values. tabindex="0" inserts an element into the natural DOM-order tab sequence. tabindex="-1" makes an element programmatically focusable (via JS) but removes it from Tab key navigation. Positive values (tabindex="1", "2"...) create a custom order that almost always conflicts with user expectations and should be avoided.
tabindex Values. Why is tabindex="5" generally considered an anti-pattern?
- āIt's technically invalid HTML and gets ignored
- āIt creates a custom tab order that overrides and conflicts with natural DOM order
- āIt measurably slows down page rendering
Custom Widgets Need Real Key Handling. Native elements come with built-in key behavior: Space toggles a checkbox, arrow keys move through a select's options. Any custom widget built from generic elements must reimplement the expected key conventions for its role, or it breaks user expectations set by every other accessible site.
Widget Key Conventions. You build a custom role="tablist" component. Users expect which keys to move focus between tabs, based on the standard ARIA tab pattern?
- āThe Tab key, cycling through every tab individually
- āLeft/Right arrow keys, with Tab moving out of the whole widget
- āNumber keys 1-9 matching each tab's position
Keyboard Fluency Achieved. You now understand how tab order is computed, when tabindex values help or hurt, and why custom widgets must reimplement standard key conventions to remain operable without a mouse.
Make A Div Behave Like A Button. A div acting as a button needs both role="button" and tabindex="0" to be keyboard-operable.
Level Up š
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1WCAG 2.1.1 Keyboard Requires Zero Mouse-Only Functionality
Every action available via mouse, including drag-and-drop and hover-triggered menus, must have a keyboard-operable equivalent, with no exceptions carved out for complexity.
2Focus Should Be Visually Indicated At All Times During Keyboard Use
Removing focus outlines without a replacement (covered under WCAG 2.4.7) makes keyboard navigation technically possible but practically unusable, since users can't see where they are.
SEO Implications
- 1
Logical Tab Order Correlates With Logical Document Structure
A page whose DOM order matches its visual/reading order ā good for tab order ā is also easier for search engines to parse into a coherent content hierarchy.
- 2
Keyboard-Operable Interactive Content Is More Likely To Be Crawlable
Content that only reveals itself on mouse hover or drag often isn't reachable by crawlers either, since both crawlers and keyboard users lack a mouse pointer.
Best Practices
Keep Visual Order And DOM Order Aligned Wherever Possible
It keeps tab order intuitive for keyboard users without requiring any tabindex workarounds, and it's simpler to maintain than fighting CSS reordering with manual tab-index management.
Follow The ARIA Authoring Practices Guide's Key Conventions For Any Custom Widget
The APG documents the exact expected keyboard behavior for every common widget pattern (tabs, menus, comboboxes, dialogs) ā following it guarantees your widget behaves the way users already expect.
Frequent Bugs
A user tabs through a page and focus visually jumps around unpredictably.
DOM order and CSS visual order have diverged. Reorder the underlying markup to match the intended visual/reading order instead of relying on CSS alone.
A custom dropdown opens with a click but pressing Escape or arrow keys does nothing.
The widget has no keydown handlers implementing the expected combobox key conventions. Add Escape-to-close and Arrow-key-to-navigate handling per the ARIA APG combobox pattern.
Real-World Examples
Focus Move Into A Route-Changed View
A single-page app moves keyboard focus to the new page's heading after client-side navigation, so screen reader and keyboard users aren't stranded on a stale focus target.
const heading = document.getElementById('page-title');
heading.setAttribute('tabindex', '-1');
heading.focus();