Focus Order
Must
Section 508:
- §1194.21(a)
- §1194.31(a)
- §1194.31(b)
- §1194.31(f)
WCAG 2.0:
- 1.3.2
- 2.4.3
Actionable content must be navigable in a meaningful sequence
The focus order of interactive elements on the page should follow a logical progression of steps based on the logic of the page. This order typically follows the order in which elements were placed in the app. When the order is not correct, filling out forms or navigating through the page extremely cumbersome.
Actionable content must be navigable in a meaningful sequence that keeps the meaning and operation intact when using a keyboard or like input alternative.
iOS
Focus order in iOS is determined by physical layout of controls/views. Developers can control and change this order by using the UIAccessibilityContainer
protocol if they need to.
iOS Example
//order in the storyboard the same as the view order <scene sceneID="5"> <objects> <viewController ...> <view ...> <rect ... /> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <subviews> <label ... text="Username"> ... </label> <textField ...> <accessibility key="accessibilityConfiguration" label="Username"/> ... </textField> <label ... text="Password"> ... </label> <textField ...> <accessibility key="accessibilityConfiguration" label="Password"/> ... </textField> <button ...> <accessibility key="accessibilityConfiguration" label="Log-in"/> ... </button> </subviews> ... </view> </viewController> //Use transparent subview for the textFields and shouldGroupAccessibilityChildren on the subview <scene sceneID="5"> <objects> <viewController ...> <view ...> <rect ... /> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <subviews> <view ... id="cgi-H2-Ej8"> <subviews> <label ... text="Username"> ... </label> <textField ...> <accessibility key="accessibilityConfiguration" label="Username"/> ... </textField> <label ... text="Password"> ... </label> <textField ...> <accessibility key="accessibilityConfiguration" label="Password"/> ... </textField> <subviews> </view> <button ...> <accessibility key="accessibilityConfiguration" label="Log-in"/> ... </button> </subviews> ... </view> </viewController> @interface ViewController : UIViewController @property (weak, nonatomic) IBOutlet UIView *TextInputsView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. _TextInputsView.shouldGroupAccessibilityChildren = YES; }
iOS Failure
//order in the storyboard is: //Log-in //Password //Username <scene sceneID="5"> <objects> <viewController ...> <view ...> <rect ... /> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <subviews> <button ...> <accessibility key="accessibilityConfiguration" label="Log-in"/> ... </button> <label ... text="Password"> ... </label> <textField ...> <accessibility key="accessibilityConfiguration" label="Password"/> ... </textField> <label ... text="Username"> ... </label> <textField ...> <accessibility key="accessibilityConfiguration" label="Username"/> ... </textField> </subviews> ... </view> </viewController>
Android
The focus order will fall to the nearest, neighboring, focusable element by default. Sometimes this may not match what is intended and as such explicit overrides may need to be provided.
This can be done by using the following:
android:nextFocusDown
defines the next view to receive focus when the user navigates downandroid:nextFocusLeft
defines the next view to receive focus when the user navigates left,android:nextFocusRight
defines the next view to receive focus when the user navigates right,android:nextFocusUp
defines the next view to receive focus when the user navigates up.
Android Example
// button 1 moves to 2 and then 3 and then back around to 1 <LinearLayout android:orientation="vertical" ... > <Button android:id="@+id/btn1" android:nextFocusUp="@+id/btn3" android:nextFocusDown="@+id/btn2"... /> <Button android:id="@+id/btn3" android:nextFocusUp="@+id/btn2" android:nextFocusDown="@+id/btn1" ... /> <Button android:id="@+id/btn2" android:nextFocusUp="@+id/btn1" android:nextFocusDown="@+id/btn3" ... /> </LinearLayout>
Android Failure
// button order is not cyclical and goes from 1 to 3 to 2 <LinearLayout android:orientation="vertical" ... > <Button android:id="@+id/btn1" ... /> <Button android:id="@+id/btn3" ... /> <Button android:id="@+id/btn2" ... /> </LinearLayout>
HTML
The following will ensure a logical content order:
- Code according to tab order
- tabIndex (positive, '0' and negative) may not be supported in mobile browsers
- Tables should not be used for layout purposes
HTML 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>
HTML Failure
<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>
Remediating
Ensure the focus order of all interactive elements is correct. in iOS the focus order follows the reading order. This is left-right and top-bottom by default. When multiple elements in the vertical plane should be read before some on the horizontal plane, wrap them in a transparent view and set shouldGroupAccessibilityChildren to true.
Testing
Recommended tool/method: Manual / Screen Reader
Ensure the focus order of interactive elements on the page is logical
- Activate the application with a screen reader
- Navigate through the active on-screen object, elements, and controls
- Verify that the focus order is equivalent to the intuitive visual reading order of the page
- Select radio buttons, checkboxes and other actionable object, elements, and controls
- If additional item appear or become enabled, determine if these items are later in the focus order. Newly appearing fields should appear later in the focus order
- Ensure focus moves forward and backward in an intuitive manner
Android has a focus emulator that can be used in the absence of a directional controlle