Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guideline for live regions #1027

Closed
wants to merge 14 commits into from
386 changes: 385 additions & 1 deletion aria-practices.html
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ <h4>WAI-ARIA Roles, States, and Properties</h4>
<li>The element that serves as an input and displays the combobox value has role <a href="#combobox" class="role-reference">combobox</a>.</li>
<li>
The combobox element has <a href="#aria-controls" class="property-reference">aria-controls</a> set to a value that refers to the element that serves as the popup.
Note that <code>aria-controls</code> only needs to be set when the popup is visible. However, it is valid to reference an element that is not visible.
Note that <code>aria-controls</code> only needs to be set when the popup is visible. However, it is valid to reference an element that is not visible.
</li>
<li>The popup is an element that has role <a href="#listbox" class="role-reference">listbox</a>, <a href="#tree" class="role-reference">tree</a>, <a href="#grid" class="role-reference">grid</a>, or <a href="#dialog" class="role-reference">dialog</a>.</li>
<li>
Expand Down Expand Up @@ -3734,6 +3734,390 @@ <h5>Examples</h5>
</section>
</section>

<section id="live_regions">
<h2>Live Regions</h2>

<p>
Live regions are perceivable regions of a web page that are typically updated as a result of an external event when user focus might be elsewhere.
These regions are not always updated as a result of a user interaction.
By marking such elements as live regions, users of assistive technology can be informed of the updated content automatically.
</p>

<p>
Examples of live regions are a chat log and an error message.
However, different kinds of live regions have different expected behavior;
users might expect an error message to disrupt what they are doing, since the error is important,
but want to wait with reading new chat messages until they are done typing their own message.
</p>

<section id="live_region_states_and_properties">
<h3>Live Region States and Properties</h3>

<p>
ARIA has the following attributes mark up live regions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ARIA has the following attributes mark up live regions.
ARIA has the following attributes to mark up live regions.

</p>

<table>
<thead>
<tr>
<th>State/property</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>aria-live</code></td>
<td>Enables a live region.</td>
</tr>
<tr>
<td><code>aria-atomic</code></td>
<td>Indicates what content to announce.</td>
</tr>
<tr>
<td><code>aria-relevant</code></td>
<td>Indicates which content changes are relevant.</td>
</tr>
<tr>
<td><code>aria-busy</code></td>
<td>Defers content updates. Not specific to live regions. See the <a href="#aria-busy">next section</a>.</td>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<td>Defers content updates. Not specific to live regions. See the <a href="#aria-busy">next section</a>.</td>
<td>Defers announcement of content updates. Not specific to live regions. See <a href="#defer_exposing_content_updates_using_aria-busy">Defer Exposing Content Updates using aria-busy</a>.</td>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This helps!

</tr>
</tbody>
</table>

<section id="enable_live_regions_with_aria-live">
<h4>Enable Live Regions with <code>aria-live</code></h4>

<p>
The <code>aria-live</code> attribute indicates that an element is a live region.
Some roles implicitly set <code>aria-live</code>; this is discussed in a later section.
</p>

<ul>
<li><code>assertive</code>: assistive technologies can interrupt the user to provide this information,
but will not move the current focus, so the user&#39;s work flow is not interrupted.</li>

<li><code>polite</code>: assistive technologies will provide this information after the user is done with their current task.</li>

<li><code>off</code>: assistive technologies will not provide this information unless this region has focus.</li>
</ul>

<p>
With the exception of a few roles, the default value of <code>aria-live</code> is <code>off</code>.
</p>

<p>
For example, when the user types into a search field, the page could update the page with search results as the user is typing.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For example, when the user types into a search field, the page could update the page with search results as the user is typing.
For example, when the user types into a search field, the page could update with search results as the user is typing.

redundant "the page"

To inform users of assistive technology that this has happened, a polite live region can be used.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To inform users of assistive technology that this has happened, a polite live region can be used.
To inform assistive technology users that this has happened, a polite live region can be used.

Remove potential confusion over "To inform users of something that happened..."

When the user is done typing, and the search is complete, the user is informed of how many results were found,
without having to move focus away from the search field.
</p>

<pre><code>&lt;form role="search" aria-labelledby="search">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside: What tool is being used to convert from markdown to markup? It seems to have a bug where it outputs &lt; instead of < inside <pre><code> examples, which makes github changes harder to read. If possible, please open an issue against the conversion tool. Thanks! :)

&lt;h2 id="search">Search&lt;/h2>
&lt;label>Search query: &lt;input type="search" name="q" oninput="updateSearch(event)">&lt;/label>
&lt;div id="search-result-status" role="region" aria-live="polite">&lt;/div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

region is a landmark role.

Need to discuss with group whether a live region can use role="region" without being a landmark.

If so, then the ARIA spec needs to allow this use specifically for live regions.

Or, if the live region in this example is truly intended to be a landmark, then in needs an accessible name (or else conformance tools are going to flag it as missing one).

If, however, the group decides that role="region" should not be allowed on live regions without turning them into landmarks, and if it is decided that the live region in this example should not be a landmark (really, I think the role here should be "status", but we haven't described that yet), then we need to know what role, if any, should go on this example's live region div. (No role, i.e. "generic"? Or "group", perhaps? Or should we just use "status" role before it is discussed?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's not named then it shouldn't have a role=region. does this example even need a role?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this example even need a role?

Nope. :) Decision on the call was to delete role=region and leave it with no role.
(The "Contacts list" example later on can keep region and label because it's ok as a true landmark).

I didn't want to state "No role" as the "best" choice without floating a bunch of other possibilities out there first - even the wacky possibility of changing the spec to allow live region elements to have a "non-landmark role=region". 😄

&lt;/form>
&lt;script>
async function updateSearch(event) {
const statusElement = document.getElementById(&#39;search-result-status&#39;);
const results = await getSearchResults(event.target.value);
statusElement.textContent = `${results.length} result(s) found.`;
showResults(results);
}
&lt;/script>
</code></pre>
</section>

<section id="indicate_what_content_to_announce_with_aria-atomic">
<h4>Indicate What Content to Announce with <code>aria-atomic</code></h4>

<p>
The <code>aria-atomic</code> attribute takes the values "true" and "false". The attribute can also be omitted.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The <code>aria-atomic</code> attribute takes the values "true" and "false". The attribute can also be omitted.
The <code>aria-atomic</code> attribute takes the values "true" and "false". The attribute can also be omitted, as discussed below.

To keep the first-time reader from thinking that discussion of the default value must be missing.

</p>

<p>
When this attribute is set to <code>true</code>, assistive technologies will render the element as a whole, and not just parts that have been changed.
</p>

<p>
When this attribute is set to <code>false</code>, assistive technologies will only render the changes (as per <code>aria-relevant</code>) to the user.
</p>

<p>
When this attribute is omitted, the user agent will use the closest ancestor that has <code>aria-atomic</code> set to <code>true</code> or <code>false</code>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When this attribute is omitted, the user agent will use the closest ancestor that has <code>aria-atomic</code> set to <code>true</code> or <code>false</code>,
When this attribute is omitted, the user agent will use the value of <code>aria-atomic</code> from the closest ancestor that has <code>aria-atomic</code> set to <code>true</code> or <code>false</code>,

or if there is no such ancestor, <code>false</code>.
</p>

<p>
For example, consider a clock that can be set to notify the user of the current time at a regular interval.
Without <code>aria-atomic</code>, the assistive technology might only notify the changed components, rather than the full time.
</p>

<pre><code>&lt;div id="clock" role="region" aria-live="polite" aria-atomic="true">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous discussion about role="region".

The time is
&lt;span>16&lt;/span>:&lt;span>34&lt;/span>:&lt;span>05&lt;/span>
&lt;/div>
</code></pre>
</section>

<section id="indicate_which_content_changes_are_relevant_with_aria-relevant">
<h4>Indicate Which Content Changes are Relevant with <code>aria-relevant</code></h4>

<p>
The <code>aria-relevant</code> attribute can be used to inform assistive technologies about which kinds of changes are relevant to inform users about.
It takes a list of keywords, with the following meanings:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It takes a list of keywords, with the following meanings:
It takes a space-separated list of keywords, with the following meanings:

</p>

<ul>
<li><code>additions</code>: Element nodes are added to the accessibility tree within the live region.</li>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<li><code>additions</code>: Element nodes are added to the accessibility tree within the live region.</li>
<li><code>additions</code>: When element nodes are added to the accessibility tree within the live region.</li>

Consider adding "When" to these (short for "Relevant when...").

<li><code>text</code>: Text content or a text alternative is added to any descendant in the accessibility tree of the live region.</li>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<li><code>text</code>: Text content or a text alternative is added to any descendant in the accessibility tree of the live region.</li>
<li><code>text</code>: When text content or a text alternative is added to any descendant in the accessibility tree of the live region.</li>

<li><code>removals</code>: Text content, a text alternative, or an element node within the live region is removed from the accessibility tree.</li>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<li><code>removals</code>: Text content, a text alternative, or an element node within the live region is removed from the accessibility tree.</li>
<li><code>removals</code>: When text content, a text alternative, or an element node within the live region is removed from the accessibility tree.</li>

<li><code>all</code>: Synonym to <code>additions removals text</code></li>
</ul>

<p>
If <code>aria-relevant</code> is not specified, then the value of the closest ancestor element with an <code>aria-relevant</code> attribute is used.
Specifying the <code>aria-relevant</code> attribute on an element overrides any value specified on an ancestor element.
If there is no ancestor element with an <code>aria-relevant</code> attribute, the default value <code>additions text</code> is used.
</p>

<p>
For example, a disappearing old message in a chat log is not significant, and users do not need to be informed of the removal.
However, for a list of online contacts, a disappearing contact is significant (it indicates that the contact is no longer online).
Instead of announcing the removal of something, it is often better to add new content that tells the user what happened.
For example, "Alice is now offline" is clearer than "Alice" or "Removed, Alice".
Therefore, avoid using <code>removals</code> or <code>all</code>.
</p>

<p>
For example, a list of online contacts:
</p>

<pre><code>&lt;div role="region" aria-live="polite" aria-labelledby="contacts">
Copy link
Contributor

@carmacleod carmacleod Jan 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See note above regarding role="region". Note that in this particular example, since the region has a name ("Contacts") it will definitely be a landmark. For this particular example, this is probably what the author wants - it likely makes sense (depending on the app, of course) to have the contacts list be a landmark, therefore easily navigable. I'm just flagging this to include it in the discussion.

&lt;h1 id="contacts">Contacts&lt;/h1>
&lt;ul>
&lt;li aria-atomic="true">&lt;a href="/contacts/alice">Alice&lt;/a> is now online&lt;/li>
&lt;/ul>
&lt;/div>
</code></pre>

<p>
Note that this example omits the <code>aria-relevant</code> attribute, leaving it as the default value (<code>additions text</code>).
</p>

<p>
When a contact comes online, it is added to the list, and users of assistive technology are informed of the addition without disrupting their current task.
To communicate what happened, the text is "Alice is now online", rather than only "Alice".
</p>

<p>
Similarly when a user goes offline, the text could be changed to "Alice is now offline",
and then be hidden from the list after a timeout.
</p>

<p>
If a contact changes their display name, the text change would also be announced:
"Alice has changed their name to 4liz".
After a timeout, the text "Alice has changed their name to " could be removed, without causing a new announcement.
</p>
</section>

<section id="triggering_live_regions">
<h4>Triggering Live Regions</h4>

<p>
Additions and removals in the accessibility tree can happen due to changes to the DOM tree or changes to the applied CSS.
For example, changing the CSS <code>display</code> property to <code>none</code> causes the element to be removed from the accessibility tree.
See the <a href="#accessibility-tree">Accessibility tree</a> section for more details.
Copy link
Contributor

@carmacleod carmacleod Jan 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section needs a bit more discussion. It seems to be missing a sentence that ties in Accessibility tree changes with triggering live regions. (It's implied by the section title, but I think it needs to be explicitly stated). Something like:
"Accessibility tree changes within a live region can trigger live region announcements."

Also, does setting display: block; or visibility: visible; on the live region element trigger an announcement? Or does it have to be rendered first, and then have a change? Does changing CSS display on live region descendants trigger the live region? Maybe also mention html hidden and aria-hidden.

</p>
</section>
</section>

<section id="special_case_live_regions">
<h3>Special Case Live Regions</h3>

<p>
The roles listed below implicitly set the <code>aria-live</code> attribute to indicate that it is a live region.
When using these roles, the <code>aria-live</code> attribute can be omitted,
or it can be specified to change the value from the default.
</p>

<ul>
<li><code>alert</code></li>
<li><code>log</code></li>
<li><code>status</code></li>
<li><code>timer</code></li>
<li><code>marquee</code></li>
</ul>

<section id="live_region_role_alert">
<h4>Live Region Role <code>alert</code></h4>

<p>
The <code>alert</code> role indicates important, usually time-sensitive, information.
Use this role when focus is not moved to the message, and the user is not expected to close the message.
For an alert dialog that can be closed, the the <code>alertdialog</code> role instead.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For an alert dialog that can be closed, the the <code>alertdialog</code> role instead.
For an alert dialog that can be closed, use the <code>alertdialog</code> role instead.

</p>

<p>
The default value for <code>aria-live</code> is <code>assertive</code>.
The default value for <code>aria-atomic</code> is <code>true</code>.
</p>

<p>
See the <a href="#alert">Alert design pattern</a> and the related <a href="https://w3c.github.io/aria-practices/examples/alert/alert.html">Alert Example</a>.
</p>
</section>

<section id="live_region_role_log">
<h4>Live Region Role <code>log</code></h4>

<p>
The <code>log</code> role indicates that new information is added in meaningful order and old information might disappear.
</p>

<p>
The default value for <code>aria-live</code> is <code>polite</code>.
</p>

<p>
For example, a chat log would be an appropriate use case for the <code>log</code> role.
</p>

<pre><code>&lt;h1 id="irc-log">IRC Log&lt;/h1>
&lt;div role="log" aria-labelledby="irc-log">
&lt;p>[10:26] &amp;lt;Charl> ok let&#39;s test it and see if it works&lt;/p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
&lt;p>[10:26] &amp;lt;Charl> ok let&#39;s test it and see if it works&lt;/p>
&lt;p>[10:26] <Charl> ok let&#39;s test it and see if it works&lt;/p>

This instance of &lt; was changed to &amp;lt; by the markdown-to-markup conversion, and that ends up being surfaced in the document. Important to have the converter fixed, or maybe just start with markup instead, to make changes easier to read. For example, this code contains let&#39;s instead of let's and &lt; in front of every html tag.

&lt;p>[10:59] &amp;lt;hsivonen> morning&lt;/p>
&lt;/div>
</code></pre>
</section>

<section id="live_region_role_status">
<h4>Live Region Role <code>status</code></h4>

<p>
The <code>status</code> role indicates that content is advisory information for the user but is not important enough to justify an <code>alert</code>, often but not necessarily presented as a status bar.
</p>

<p>
The default value for <code>aria-live</code> is <code>polite</code>.
The default value for <code>aria-atomic</code> is <code>true</code>.
</p>

<p>
Do not move focus to the element with script when the content is changed.
</p>

<p>
For example, the search result summary example above could use <code>role="status"</code> instead of <code>role="region"</code>:
</p>

<pre><code>&lt;form role="search" aria-labelledby="search">
&lt;h2 id="search">Search&lt;/h2>
&lt;label>Search query: &lt;input type="search" name="q" oninput="updateSearch(event)">&lt;/label>
&lt;div id="search-result-status" role="status">&lt;/div>
&lt;/form>
</code></pre>

<p>
The HTML <code>output</code> element has the <code>status</code> role by default.
The <code>output</code> element is defined to represent the result of a calculation performed by the application, or the result of a user action.
The result of a user search is thus appropriate use of the <code>output</code> element:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The result of a user search is thus appropriate use of the <code>output</code> element:
The result of a user search is thus an appropriate use of the <code>output</code> element:

</p>

<pre><code>&lt;form role="search" aria-labelledby="search">
&lt;h2 id="search">Search&lt;/h2>
&lt;label>Search query: &lt;input type="search" name="q" oninput="updateSearch(event)">&lt;/label>
&lt;output id="search-result-status">&lt;/output>
&lt;/form>
</code></pre>
</section>

<section id="live_region_role_timer_and_marquee">
<h4>Live Region Role <code>timer</code> and <code>marquee</code></h4>

<p>
Usage of the <code>timer</code> and <code>marquee</code> roles is discouraged.
</p>

<p>
The <code>timer</code> role is a numerical counter which indicates an amount of elapsed time from a start point, or the time remaining until an end point.
The <code>timer</code> role is a subclass of the <code>status</code> role.
The default value of <code>aria-live</code> value of <code>off</code>.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The default value of <code>aria-live</code> value of <code>off</code>.
The default value of <code>aria-live</code> is <code>off</code>.

Redundant "value of".

</p>

<p>
The <code>marquee</code> role indicates non-essential information that changes frequently.
The default value of <code>aria-live</code> value of <code>off</code>.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove redundant "value of".

Suggested change
The default value of <code>aria-live</code> value of <code>off</code>.
The default value of <code>aria-live</code> is <code>off</code>.

</p>

<p class="note">
<a href="https://github.com/w3c/aria/issues/1104">Issue 1104 for the ARIA specification</a> proposes deprecating these roles.
</p>
</section>
</section>
</section>

<section id="defer_exposing_content_updates_using_aria-busy">
<h2>Defer Exposing Content Updates using <code>aria-busy</code></h2>

<p>
Sometimes, it takes some time for a script to update the content of a live region or a widget.
For example, it could be waiting on a network response.
In order to avoid rendering half-baked content to users of assistive technology,
the <code>aria-busy</code> attribute can be set to <code>true</code> while the content is being updated,
and then to <code>false</code> when it is done.
</p>

<p>
The ARIA specification allows, but does not require, assistive technologies to wait until <code>aria-busy</code> is changed to <code>false</code> before exposing content changes to the user.
So assistive technologies are allowed to ignore the <code>aria-busy</code> attribute.
</p>

<p>
For assistive technologies that honor the <code>aria-busy</code> attribute, one possible implementation strategy is to not announce any content for elements when <code>aria-busy</code> is set to <code>true</code>.
Therefore, it is important that the attribute is changed back to <code>false</code> when the content ought to be available to the user.
For example, when the update is complete, but also when there is an error, or if the update is aborted.
Otherwise, content could be left inaccessible to assistive technology users.
</p>

<p>
Consider the search form from the earlier example in the <a href="#live-regions">Live Resions</a> section.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Consider the search form from the earlier example in the <a href="#live-regions">Live Resions</a> section.
Consider the search form from the earlier example in the <a href="#live-regions">Live Regions</a> section.

When the user starts typing a new search into the search field, the script would update the search results live region,
and maybe update multiple times as new search results appear,
but it would be a better experience for users of assistive technology to only be notified when the new search is complete.
</p>

<pre><code>&lt;form role="search" aria-labelledby="search">
&lt;h2 id="search">Search&lt;/h2>
&lt;label>Search query: &lt;input type="search" name="q" oninput="updateSearch(event)">&lt;/label>
&lt;div id="search-result-status" role="region" aria-live="polite">&lt;/div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See earlier discussion about role="region".
For this example, consider simply using role="status" (in which case, aria-live="polite" can be removed).

&lt;/form>
&lt;script>
async function updateSearch(event) {
const statusElement = document.getElementById(&#39;search-result-status&#39;);
statusElement.ariaBusy = &#39;true&#39;;
statusElement.textContent = &#39;Searching...&#39;;
let results = null;
try {
results = await getSearchResults(event.target.value);
statusElement.textContent = `${results.length} result(s) found.`;
} catch (ex) {
statusElement.textContent = "There was an error when searching. Please try again.";
}
statusElement.ariaBusy = &#39;false&#39;;
showResults(results);
}
&lt;/script>
</code></pre>

<p>
The <a href="#feed">Feed Design Pattern</a> uses <code>aria-busy</code> in its example.
A feed is a section of a page that automatically loads new sections of content as the user scrolls.
While the feed is loading new content, <code>aria-busy</code> is set to <code>true</code> on the feed.
</p>
</section>

<section id="names_and_descriptions">
<h2>Providing Accessible Names and Descriptions</h2>
<p>
Expand Down
Loading