This document is in beta. Help us by reporting issues via Github or email
On this page:
Make sure that elements appear in a logical reading order in code, so that they are presented in a meaningful order to screen reader users.
Content on the page needs to be announced by screen readers following a logical reading order.
<table>
, <tr>
, <th>
, and <td>
elements)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.
1.3.2 Meaningful Sequence: When the sequence in which content is presented affects its meaning, a correct reading sequence can be programmatically determined. (Level A)
See the W3C’s detailed explanation of this guideline with techniques and examples.
containerView.isAccessibilityElement = false
containerView.accessibilityElements = [firstLabel, secondLabel, button]
<RelativeLayout ...>
<Button
android:id="@+id/button1"
android:nextFocusForward="@+id/editText1"
... />
<Button
android:id="@+id/button2"
android:nextFocusForward="@+id/button1"
... />
<EditText
android:id="@id/editText1"
android:nextFocusForward="@+id/button2"
... />
...
</RelativeLayout>
Alternative from API 22 is to specify the traversal order android:accessibilityTraversalAfter="@id"
.
This is the recommended way but there is the API 22 restriction.
<RelativeLayout ...>
<Button
android:id="@+id/button1"
android:accessibilityTraversalAfter="@+id/editText1"
... />
<Button
android:id="@+id/button2"
android:accessibilityTraversalAfter="@+id/button1"
... />
<EditText
android:id="@id/editText1"
android:accessibilityTraversalAfter="@+id/button2"
... />
...
</RelativeLayout>
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)
Flutter deals with assistive technologies like screen readers using the Semantics()
widget. For a quick introduction of the Semantics()
widget you can read this article.
##
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()
),
]
),
tabindex
tabindex
.<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>
<div tab-index="3" class="fake_button" aria-role="button">Button Label</div>
position
order
property or flex-direction: reverse;
;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;<main>
<div style="float:left;">
<h1>Article header</h1>
<div>Article content</div>
</div>
<aside style="float:right;">Supplementary info</aside>
</main>
<main>
<h1>Article header</h1>
<aside style="position:relative; left:50%;top:-50%;">Supplementary info</aside>
<div>Article content</div>
</main>
tabindex
has been used with a value other than -1
or 0
.inert
attribute)This document is in beta. Help us by reporting issues via Github or email