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. (Level A)
This applies to native apps by replacing “Web page” with “screen”.
Requirements
- When navigated sequentially using a keyboard, interactive elements should receive focus following a predictable, natural reading order (from left to right and top to bottom, in most cases).
- The easiest way to avoid focus order issues is to make sure that elements are displayed on screen in the same order as they appear in the Document Object Model (Web) / View Hierarchy (iOS and Android).
- Manage keyboard focus manually when needed to make the interface easy to use for screen reader, Switch control and keyboard-only users.
- For example, if pressing a button triggers a modal dialog, keyboard focus should move to that dialog and stay within (rather than going back to elements behind the dialog), until the user closes the dialog.
Why is it important?
This ensures that content can be navigated in a logical way by screen reader users, keyboard users and Switch device users.
The order in which elements appear in code matters:
- Screen readers go through elements on a page/screen in the order in which they appear in the Document Object Model (Web) / View Hierarchy (iOS and Android), which is a tree-like structure that contains all the elements on the page.
- The order in which elements appear in that Document Object Model / View Hierarchy might be different from the order in which they’re laid out visually on screen.
- This can happen for example if certain CSS techniques are used to change the relative positioning of elements on the page.
- The order in which elements appear in that Document Object Model / View Hierarchy matters to user experience.
- When people use a screen reader, the keyboard or a Switch control, they interact with elements on the page in the order in which they appear in that Document Object Model / View Hierarchy.
- So make sure that elements appear in the Document Object Model / View Hierarchy in a reading order that’s natural and makes sense.
Summary
Make sure that interactive controls receive focus in an order that makes sense, when users navigate through them with the keyboard. Actionable items should receive the keyboard focus in an order that makes sense for users, and makes the interface easy to operate.
Common mistakes
- The order of interactive elements is not consistent across designs for different screen sizes.
- For example, imagine that you’ve designed a modal dialog with two buttons: ‘Cancel’ and ‘OK’:
- On the design for large screens, the ‘Cancel’ button is positioned to the left of the ‘OK’ button. (‘Cancel’ comes before ‘OK’ in the reading order).
- But on the design for small screens, the ‘Cancel’ button is positioned to the bottom of the ‘OK’ button. (‘Cancel’ now comes after ‘OK’ in the reading order).
- For example, imagine that you’ve designed a modal dialog with two buttons: ‘Cancel’ and ‘OK’:
- The DOM order does not match the visual order because CSS properties like flexbox and grid-layout have been used to alter the visual presentation;
- The DOM order does not match the visual order because
tabindex
has been used with a value other than-1
or0
. - A ‘Agree to cookies’ dialog that’s positioned last in the DOM but appears at the top of the screen, without being implemented as modal (with the
inert
attribute) - When CSS styles are disabled, the focus order is meaningless;
- Using dialogs or menus that are not adjacent to their trigger control in the sequential navigation order.
Design Guide
- When you provide different designs for different screen sizes (e.g. desktop and mobile, or for different break points), make sure that all interactive elements appear in the same order across on the different designs.
- If you can’t do that, call it out to developers as they’re likely to need to create different structures for the different designs.
- On the designs that you give to developers, and in conversations with them, indicate what the ‘keyboard focus order’ should be for interactive elements.
- Also indicate when actioning a button should move the keyboard focus somewhere else. This will help make sure that components such as dialogs can be closed easily by users.
Example: Designing a modal dialog for the Web
- Opening a modal dialog should move the keyboard focus to an element inside the modal dialog, rather than keeping the keyboard focus outside it. It’s best to move the keyboard focus to the ‘Close’ button inside the modal dialog, or to the main header within the dialog.
- The keyboard focus should stay within the modal dialog when users press the ‘Tab’ key several time, rather than go back to content behind the modal dialog.
- There should be a button to close or dismiss the modal dialog. Pressing that button should return the keyboard focus to the button that triggered modal dialog in the first place (so that the user go back to where they were on the page before opening the modal dialog).
Focus Order Example for Android
The best practices for grouping and ordering elements in an accessible manner can be summarized as follows:
- The view hierarchy order and on-screen positioning determine grouping and ordering of text in spoken feedback.
- You should group non-focusable items in a focusable container to have them read as a single item.
- To logically group related items, it is sometimes necessary to create nested ViewGroup elements (eg: a wrapping RelativeLayout for a label and its value)
<LinearLayout
...
orientation="vertical">
<RelativeLayout
...
android:focusable="true">
<TextView
... />
<TextView
... />
</RelativeLayout>
<RelativeLayout
...
android:focusable="true">
<TextView
... />
<TextView
... />
</RelativeLayout>
<RelativeLayout
...
android:focusable="true">
<TextView
... />
<TextView
... />
</RelativeLayout>
</LinearLayout>
Focus Order Example for Flutter
Flutter deals with assistive technologies like screen readers using the Semantics()
widget.
- By default all focusable widgets will be read out in the order that they are drawn on the screen from top down.
There are ways of affecting the order for custom navigation of elements with a screen reader. By passing a SemanticSortKey
to the sortKey
property of Semantics()
the element with the lower key value will be read first.
Column(
children: <Widget>[
Semantics(
sortKey: OrdinalSortKey(1), // will be read/focused second by the screen reader
child: SecondWidget()
),
Semantics(
sortKey: OrdinalSortKey(0), // will be read/focused first by the screen reader
child: FirstWidget()
),
]
),
Focus can be controlled using a FocusNode()
:
FocusNode myFocusNode;
@override
void initState() {
super.initState();
myFocusNode = FocusNode();
}
@override
void dispose() {
myFocusNode.dispose(); // Clean up your focus node by disposing it when the widget is disposed
super.dispose();
}
// A widget with the focus node
TextField(
focusNode: myFocusNode,
);
// Focusing the focus node using a fuction call
() => FocusScope.of(context).requestFocus(myFocusNode),
Focus Order Example for Web
Be careful how you order elements in the DOM is it impacts user experience
Place interactive elements in the Document Object Model in an order that makes sense for users who navigate interactive elements sequentially, like screen reader, Switch control and keyboard users
Example:
<div>
<h3>Shipping Address</h3>
<label for="n1">Name</label><input type="text">
<label for="a1">Address</label><input type="text">
...
</div>
<div>
<h3>Billing Address</h3>
<label for="n2">Name</label><input type="text">
<label for="a2">Address</label><input type="text">
...
</div>
Failure example:
<table>
<tr>
<td>Shipping Address</td>
<td>Billing Address</td>
</tr>
<tr>
<td>
<label for="n2">Name</label>
<input type="text">
</td>
<td>
<label for="n1">Name</label>
<input type="text">
</td>
</tr>
<tr>
<td>
<label for="a1">Address</label>
<input type="text">
</td>
<td>
<label for="a2">Address</label>
<input type="text">
</td>
</tr>
</table>
Manage keyboard focus when needed to make the interface easy to operate
Manage keyboard focus manually when needed to make the interface easy to use for screen reader, Switch control and keyboard-only users.
Do not use positive values with tabindex
Example:
<h1 tabindex="-1">I'm the heading for a modal dialog</h1>
...
<div tab-index="0" class="fake_button" aria-role="button">Button Label</div>
Failure example:
<div tab-index="3" class="fake_button" aria-role="button">Button Label</div>
Be careful when using CSS Float, Flexbox, Grid and position
- With CSS Flexbox, don’t use the order property or flex-direction: reverse
- With CSS Grid, be careful with manual placement of items on the grid
- When using position absolute, fixed or sticky, be careful to not detach the visual order of elements from the order in which they appear in the DOM
Make new content appear in the DOM right after the element that triggers it
- If a button triggers extra content to appear (like a menu), make sure that that extra content appears next to the button in both the DOM order and visual order.
How to test whether elements appear in a logical reading order in the DOM
- Use the ‘Tab’ key to go through interactive elements on a page. Check that interactive elements receive keyboard focus in an order that makes sense and makes the interface easy to operate.
- Alternatively, turn off CSS on the page to see elements laid out on screen in the order in which they appear in the Document Object Model.
References
- Placing the interactive elements in an order that follows sequences and relationships within the content technique in the Web Content Accessibility Guidelines
- ARIA Authoring Practices Guide – Keyboard support and focus management
- FlexBox and the keyboard navigation disconnect
- Writing CSS with Accessibility in Mind: Taking care of order by Manuel Matuzovic
- The Dark Side of the Grid: Changing visual order by Manuel Matuzovic
- Using the tabindex attribute
- Accessibility Guidelines- Github.io