Requires that focusable elements receive focus in an order that preserves meaning and operability.
When you press Tab, focus should move in the order that makes sense: usually top to bottom and left to right, following the content. If focus jumps from the first field to the last, or into a menu at the top of the page, keyboard users lose their place and may submit forms with the wrong data.
This criterion requires that 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. There may be more than one valid order, but one must be provided.
tabindex values that scramble the order (F44), and dialogs or menus that are not adjacent to their trigger (F85).Keyboard-only users and switch users, who follow the focus order. Screen reader users, who move through the page sequentially. People with low vision who use magnifiers and see only a part of the page, so a sudden jump takes focus out of view. People with cognitive disabilities, who need a predictable order.
The European Accessibility Act (Directive (EU) 2019/882) applies to in-scope products and services placed on the market after 28 June 2025. Recital 47 names four principles for websites and mobile applications: perceivable, operable, understandable and robust. A logical focus order is part of "operable".
The technical counterpart is the standard EN 301 549, which incorporates WCAG 2.4.3 by reference and turns it into separate clauses for each kind of ICT.
| Clause | Type of ICT | What it requires |
|---|---|---|
| 9.2.4.3 | Web pages | Web content must satisfy WCAG success criterion 2.4.3. |
| 10.2.4.3 | Non-web documents (PDF, Office files) | Documents must have a focus order that preserves meaning and operability where the standard applies the criterion to them. |
| 11.2.4.3 | Non-web software (native mobile apps) | Software must have a focus order that preserves meaning and operability. |
Whether and how the criterion applies to non-web documents is stated in clause 10 of the standard. Clause numbers follow the "9. + WCAG number" pattern of EN 301 549. In V3.2.1 the software clause is divided into further subclauses for open and closed functionality. Check the exact numbers in the standard when you cite them.
Standard version: EN 301 549 V4.1.1 (September 2026) is based on WCAG 2.2 and is the first version prepared specifically for the EAA. It has not yet been cited in the Official Journal of the European Union, so for now it is best treated as a voluntary technical route to the EAA's requirements. Once cited, it will give a presumption of conformity. The text of criterion 2.4.3 is the same in WCAG 2.1 and 2.2.
A note on EAA scope: Article 2(4) of the Directive excludes certain content from the requirements, for example office file formats published before 28 June 2025 and archives that are not updated after that date. Content you publish or change after that date is not covered by these exclusions.
Directive (EU) 2019/882, EUR-Lex, opens in a new tab
CSS can move things visually without changing the order of focus.
.form { display: flex; flex-direction: column-reverse; }
/* Tab goes to the last field first */.form { display: flex; flex-direction: column; }
/* DOM order and visual order are the same */tabindex values above 0 take elements out of the natural order and are very hard to maintain (F44).
<input tabindex="3">
<input tabindex="1">
<input tabindex="2"><input>
<input>
<input>tabindex="-1" only for scripted focusA value of -1 lets a script focus an element, for example a heading, without adding it to the Tab sequence.
<div tabindex="0">Static paragraph</div><h2 id="results" tabindex="-1">Results</h2>
<script>document.getElementById("results").focus();</script>Move focus into the dialog when it opens, keep the page behind it inert, and put focus back on the trigger when it closes (H102).
<div class="modal">…</div> <!-- appended at the end of the page, focus stays behind --><button id="open">Edit profile</button>
<dialog id="profile">
<h2>Edit profile</h2>
…
<button type="button" id="close">Close</button>
</dialog>
<script>
open.onclick = () => profile.showModal();
close.onclick = () => { profile.close(); open.focus(); };
</script>Insert dynamic content next to its trigger so that Tab leads straight into it.
document.body.appendChild(panel); // far from the triggertrigger.insertAdjacentElement("afterend", panel);Do not wrap a focusable control in another focusable element. The control then receives focus twice.
<div tabindex="0" onclick="go()"><button>Open</button></div><button onclick="go()">Open</button>Screen readers and switch access follow a traversal order on mobile as well. It normally follows the layout, and you only adjust it when the visual layout and the logical order differ.
import SwiftUI
struct PriceCard: View {
var body: some View {
ZStack {
// Visually the price sits on top, but the name should be read first
Text("Trail running shoes")
.accessibilitySortPriority(2)
Text("$89")
.accessibilitySortPriority(1)
}
// Group so that VoiceOver treats the card as one container
.accessibilityElement(children: .contain)
}
}import androidx.compose.foundation.layout.Box
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.traversalIndex
@Composable
fun PriceCard() {
Box(modifier = Modifier.semantics { isTraversalGroup = true }) {
// The visual position and the reading order differ, so set the order explicitly
Text("$89", modifier = Modifier.semantics { traversalIndex = 1f })
Text("Trail running shoes", modifier = Modifier.semantics { traversalIndex = 0f })
}
}tabindex values above 0 and for CSS that reorders content visually.tabindex values but cannot say if an order makes sense. A person must walk through it.tabindex values: They create a custom order that nobody maintains.order, column-reverse and absolute positioning separate focus from the visual layout.div around a button.