2.4.3 Focus Order
If a web page can be navigated sequentially and the navigation sequences affect meaning or operation, focusable components receive focus in an order that preserves meaning and operability.
What this rule means
WCAG 2.4.3 requires that when users navigate a page sequentially — typically using the Tab key — the order in which elements receive focus must be logical and meaningful. The focus order should follow the visual reading order and preserve the relationships between content elements.
This criterion applies to all interactive elements: links, buttons, form fields, and custom widgets. The DOM order should match the visual presentation so that keyboard navigation feels natural and predictable.
Why it matters
Keyboard users rely on a predictable focus order to navigate and operate web pages. When focus jumps unexpectedly — from the main content to the footer, then back to the sidebar — users become disoriented and may miss important content or controls. This is especially challenging for users with cognitive disabilities or low vision who cannot easily track where focus has moved.
A logical focus order also ensures that form workflows proceed naturally, multi-step processes work correctly, and modal dialogs trap focus properly. Broken focus order can make entire features unusable for keyboard-only users.
Related axe-core rules
- focus-order-semantics — Ensures elements in the focus order have an appropriate role.
- tabindex — Ensures tabindex attribute values are not greater than 0, which would override the natural focus order.
How to test
- Disconnect your mouse and navigate the entire page using only the Tab and Shift+Tab keys.
- Verify that focus moves through interactive elements in a logical, visual reading order (typically left-to-right, top-to-bottom for LTR languages).
- Check that no interactive elements are skipped or receive focus out of sequence.
- Test forms to confirm focus moves through fields in the expected order.
- Open modals and dialogs — verify focus is trapped inside and returns to the trigger element on close.
- Run axe-core and check for tabindex violations where tabindex > 0 is used.
- Use the browser's accessibility inspector to review the tab order overlay.
How to fix
The primary fix is to ensure your DOM order matches your visual order. Avoid using positive tabindex values and be cautious with CSS properties that reorder visual layout.
Correct DOM order vs CSS visual reordering
<!-- Bad: Visual order differs from DOM order due to CSS -->
<div style="display: flex; flex-direction: row-reverse;">
<button>Third visually, first in DOM</button>
<button>Second visually, second in DOM</button>
<button>First visually, third in DOM</button>
</div>
<!-- Good: DOM order matches visual order -->
<div style="display: flex;">
<button>First</button>
<button>Second</button>
<button>Third</button>
</div>
Avoid positive tabindex
<!-- Bad: Positive tabindex forces unnatural order -->
<input tabindex="3" placeholder="Name">
<input tabindex="1" placeholder="Email">
<input tabindex="2" placeholder="Phone">
<!-- Good: Natural DOM order, no tabindex needed -->
<input placeholder="Name">
<input placeholder="Email">
<input placeholder="Phone">
<!-- Acceptable: tabindex="0" adds to natural order -->
<div role="button" tabindex="0">Custom button</div>
<!-- Acceptable: tabindex="-1" removes from tab order -->
<div id="modal-container" tabindex="-1">...</div>
Modal focus trap
// Trap focus inside a modal dialog
function trapFocus(modalElement) {
const focusable = modalElement.querySelectorAll(
'a[href], button:not([disabled]), input:not([disabled]),\
select:not([disabled]), textarea:not([disabled]),\
[tabindex]:not([tabindex="-1"])'
);
const first = focusable[0];
const last = focusable[focusable.length - 1];
modalElement.addEventListener('keydown', (e) => {
if (e.key !== 'Tab') return;
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
});
first.focus();
}
Common mistakes
- Using positive tabindex values (tabindex="1", tabindex="2", etc.) which override natural DOM order and create confusing navigation.
- Using CSS flexbox order, grid placement, or float to visually reorder elements without matching the DOM order.
- Dynamically inserting content above the current focus position, causing users to lose their place.
- Not trapping focus inside modal dialogs, allowing users to tab to obscured content behind the overlay.
- Failing to return focus to the trigger element when closing a modal or popover.
- Using display:none to hide elements that are still focusable due to tabindex attributes.
Resources
- WebAIM: Keyboard Accessibility— WebAIM
- W3C WAI: ARIA Dialog Modal Pattern— W3C WAI
- Deque: tabindex Rule— Deque University