Main content

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:

  1. android:nextFocusDown defines the next view to receive focus when the user navigates down
  2. android:nextFocusLeft defines the next view to receive focus when the user navigates left,
  3. android:nextFocusRight defines the next view to receive focus when the user navigates right,
  4. 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
  1. Activate the application with a screen reader
  2. Navigate through the active on-screen object, elements, and controls
  3. Verify that the focus order is equivalent to the intuitive visual reading order of the page
  4. Select radio buttons, checkboxes and other actionable object, elements, and controls
  5. 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
  6. 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