Focus Order
If a page can be navigated sequentially and the order affects meaning or operation, focusable components receive focus in an order that preserves meaning and operability.
Who this affects
Keyboard and screen reader users, who experience the page as a sequence. Focus that jumps from the header to the footer and back is disorienting and easy to get lost in.
The failure and the fix
Each example below is a self-contained page, loaded in a frame so its markup cannot affect this page. Open either one on its own to test it with a keyboard or screen reader.
Fails 2.4.3
Open the failing example in a new tab
fail.html — the problem
<h1>Contact us</h1>
<!-- FAILURE 1: positive tabindex values scramble the order. Any element with
tabindex greater than 0 jumps to the FRONT of the tab order, ahead of
everything in the document. Here the user tabs: Message, Send, Name,
Email - the reverse of the visual order.
There is essentially never a good reason to use a positive tabindex.
Use 0 to make something focusable, -1 to make it focusable by script
only, and fix the DOM order instead. -->
<form>
<div class="field">
<label for="name">Name</label>
<input type="text" id="name" tabindex="3">
</div>
<div class="field">
<label for="email">Email</label>
<input type="email" id="email" tabindex="4">
</div>
<div class="field">
<label for="msg">Message</label>
<textarea id="msg" tabindex="1"></textarea>
</div>
<button type="submit" class="button" tabindex="2">Send</button>
</form>
<!-- FAILURE 2: a dialog that never receives focus. Opening it leaves focus on
the button behind it, so a keyboard user has to Tab through the whole page
to reach the dialog - and a screen reader user is not told it opened.
Focus is also not returned to the trigger on close. -->
<p><button type="button" class="button button--secondary" onclick="openDlg()">Open help</button></p>
<div class="modal" id="dlg" hidden>
<h2>Help</h2>
<p>We reply within two working days.</p>
<button type="button" class="button" onclick="closeDlg()">Close</button>
</div>
Meets 2.4.3
Open the passing example in a new tab
pass.html — the fix
<h1>Contact us</h1>
<!-- FIX 1: no tabindex at all. The DOM order already matches the visual order,
so the browser's natural focus order is correct. This is the goal: if you
need tabindex to fix your focus order, fix your DOM instead. -->
<form>
<div class="field">
<label for="name">Name</label>
<input type="text" id="name" autocomplete="name">
</div>
<div class="field">
<label for="email">Email</label>
<input type="email" id="email" autocomplete="email">
</div>
<div class="field">
<label for="msg">Message</label>
<textarea id="msg"></textarea>
</div>
<button type="submit" class="button">Send</button>
</form>
<!-- FIX 2: the dialog moves focus in when it opens and returns it to the
trigger when it closes, so the keyboard user never loses their place.
Escape closes it (2.1.2 No Keyboard Trap). -->
<p><button type="button" class="button button--secondary" id="open-help">Open help</button></p>
<div class="modal" id="dlg" role="dialog" aria-modal="true" aria-labelledby="dlg-h" hidden>
<h2 id="dlg-h" tabindex="-1">Help</h2>
<p>We reply within two working days.</p>
<button type="button" class="button" id="close-help">Close</button>
</div>
How to test it
Tab through the page and track where focus goes. It should follow the visual reading order. Watch for positive tabindex values, modals that do not move focus in, and dialogs that do not return focus on close.
-
Automated
Positive tabindex is detectable. Whether the resulting order is meaningful requires tabbing through and watching.
This demo's failure is not machine-detectable. axe does have a tabindex rule that catches positive tabindex values, but it is tagged best-practice rather than as a WCAG rule - so a scan scoped to WCAG conformance, which is how most CI pipelines are configured, reports nothing here. Whether a focus order is meaningful also cannot be computed at all.
Relevant axe rules:
tabindex
-
Keyboard
Unplug the mouse. Move through the page with Tab, Shift+Tab, Enter, Space and the arrow keys. See the keyboard testing script.
-
Screen reader
Listen to both examples with NVDA, JAWS, VoiceOver or TalkBack and compare what is announced. See the screen reader cheat sheets.
-
Visual
Zoom to 200% and 400%, narrow the viewport to 320 px, and apply the text-spacing overrides. See the visual testing procedures.
Related criteria
In the specification
- Understanding 2.4.3 Focus Order — the W3C explanation, intent and exceptions
- 2.4.3 in the WCAG 2.2 Recommendation — the normative wording
WCAG 2.2 Demo Suite