Tab order in the DOM follows these rules:
Default behavior — Elements are focused in the order they appear in the HTML source (top to bottom, left to right). Only "focusable" elements participate by default: links (), buttons, form inputs, textareas, selects, and elements with a contenteditable attribute.
The tabindex attribute overrides this in three ways:
The tabindex="0" attribute makes any element focusable and positions it in the natural DOM order. Useful for custom interactive elements like a div acting as a button.
Positive values (tabindex="1", tabindex="2", etc.) jump that element ahead of the natural order — elements with lower positive numbers come first, then the rest of the DOM flows normally after all positive-indexed elements are done. This is almost always a bad idea in practice because it creates a jarring, unpredictable experience for keyboard users.

tabindex="-1" makes an element focusable programmatically (via .focus() in JS) but removes it from the sequential tab order entirely. Handy for things like modals or dynamically shown panels that need to receive focus on demand but shouldn't be reachable via Tab key.
A quick mental model:
First, all elements with positive tabindex values, sorted ascending.
Then, everything else in DOM source order (including tabindex="0" elements).
Elements with tabindex="-1" are skipped entirely during tabbing.
if an element is hidden (display: none or visibility: hidden) or disabled, it's automatically removed from the tab order regardless of its tabindex value.
Top comments (0)