Topic 05:

Working with ARIA

Use SPACEBAR to move forward through slides.

Slide instructions

SPACEBAR to move forward through slides.

SHIFT & SPACEBAR to move backwards through slides.

LEFT ARROW & RIGHT ARROW to move through sections.

ESC to see overview and ESC again to exit.

F to enter presentation mode and ESC to exit.

5.0 Introduction

The aim for today:

  • How to build accessible modals.
  • An understanding of live regions.
  • An understanding of key aria- attributes.
  • Aria attributes that are no longer needed.
  • How to build accessible in-page tabs.

5.1
What makes an accessible modal?

Trigger element

Modals should be triggered using the <button> element rather than the <a> element, as users are performing an action, not going to a new page.

Focus

When the modal is triggered, focus should shift to either:

  • The modal container. OR
  • The first focusable element inside the modal.

In the old days, we used to send focus to the modal container as it was better supported.

More recently, it is recommended to send users to the first focusable element inside the modal.

When the modal is closed, focus should shift to either:

  • The element that triggered the modal. OR
  • Content that has changed after actions within the modal.

Keyboard

Users should not be able to TAB or SHIFT + TAB outside the modal. So, these keystrokes should be trapped inside the modal.

Users should be able to use the ESC key to close the modal and return to the page below.

Users must have the ability to close the modal using a <button> element.

Ideally, this should be the first focusable element inside the modal, even if there is a close function at the bottom of a form.

Screen readers

When the modal is triggered, three things should happen:

  1. The role is announced.
  2. An accessible name is announced.
  3. An accessible description is announced (optional).

Any questions or comments?

5.2
Exercise: Setting up a modal

Files:

Our aims are to:

  1. Set the modal with role="dialog" so it is announced when the modal is triggered.
  2. Provide the modal with an accessible name (via aria-labelledby) and description (aria-describedby), so that these are announced when the modal is triggered.
  3. Listen to the modal using a screen reader.
<div 
  id="myDialog"
  tabindex="0"
  onkeydown="escapeMe(event)"
>
  <div id="modal-content">
    <div>
      <h2>Contact details</h2>
    </div>
    <p>Make sure to...</p>
    <button>Close</button>
  </div>
</div>

Step 1:

Apply role="dialog" to parent container.

<div 
  id="myDialog"
  tabindex="0"
  onkeydown="escapeMe(event)"
  role="dialog"
>
  <div id="modal-content">
    <div>
      <h2>Contact details</h2>
    </div>
    <p>Make sure to...</p>
    <button>Close</button>
  </div>
</div>

Step 2:

Apply aria-labelledby="heading" to parent.

<div 
  id="myDialog"
  tabindex="0"
  onkeydown="escapeMe(event)"
  role="dialog"
  aria-labelledby="heading"
>
  <div id="modal-content">
    <div>
      <h2>Contact details</h2>
    </div>
    <p>Make sure to...</p>
    <button>Close</button>
  </div>
</div>

Step 3:

Apply id="heading" to <div> around the heading.

<div 
  id="myDialog"
  tabindex="0"
  onkeydown="escapeMe(event)"
  role="dialog"
  aria-labelledby="heading"
>
  <div id="modal-content">
    <div id="heading">
      <h2>Contact details</h2>
    </div>
    <p>Make sure to...</p>
    <button>Close</button>
  </div>
</div>

Step 4:

Apply aria-describedby="intro" to parent.

<div 
  id="myDialog"
  tabindex="0"
  onkeydown="escapeMe(event)"
  role="dialog"
  aria-labelledby="heading"
  aria-describedby="intro"
>
  <div id="modal-content">
    <div id="heading">
      <h2>Contact details</h2>
    </div>
    <p>Make sure to...</p>
    <button>Close</button>
  </div>
</div>

Step 5:

Apply id="intro" to paragraph.

<div 
  id="myDialog"
  tabindex="0"
  onkeydown="escapeMe(event)"
  role="dialog"
  aria-labelledby="heading"
  aria-describedby="intro"
>
  <div id="modal-content">
    <div id="heading">
      <h2>Contact details</h2>
    </div>
    <p id="intro">Make sure to...</p>
    <button>Close</button>
  </div>
</div>

Now trigger the modal and listen to how it is announced using a screen reader.

5.3
Live region states and properties

Elements that are dynamically inserted after the initial page load can cause two potential problems for screen readers.

Problem 1:

Screen readers “buffer” pages as they are loaded. Any content that is added after this time many not be picked up by the screen reader.

Problem 2:

Screen readers can only focus on one part of the page at a time. If something changes on another area of the page, screen readers may not notice this change.

The live region attributes allow authors to notify screen readers when content is updated. The possible live region attributes are:

aria-live
aria-atomic
aria-relevant
aria-busy (state)

aria-live

There are three possible values: off, polite and assertive.

Off

Assistive Technologies will be aware that changes have occurred within the element. However, these changes should not be announced unless the region is currently in focus.

The off value should be used for information that is not critical, where changes do not need to be announced.

<div aria-live="off">
</div>

Polite

Assistive Technologies should announce updates at the next graceful opportunity.

The polite value can be used for warning notifications that users may need to know.

<div aria-live="polite">
</div>

Assertive

Assistive Technologies should announce updates immediately.

The assertive value should only be used if the interruption is imperative for users to know immediately.

<div aria-live="assertive">
</div>

aria-atomic

The aria-atomic attribute indicates whether assistive technologies will present all or only parts of the changed region.

The false attribute will present only the changed regions. This is the default.

<div
  aria-live="polite"
  aria-atomic="false"
>
</div>

The true attribute will present the region as a whole when changes are detected.

<div
  aria-live="polite"
  aria-atomic="true"
>
</div>

The aria-live attribute should always be present when using the aria-atomic attribute.

<div
  aria-live="[ off | polite | assertive ]"
  aria-atomic=" [ false | true ]"
>
</div>

aria-relevant

The aria-relevant attribute defines what sorts of changes will be presented to screen readers.

The additions value informs Assistive Technologies of nodes that are dynamically inserted within the live region.

<div
  aria-live="polite"
  aria-relevant="additions"
>
</div>

The removals value informs Assistive Technologies of nodes that are dynamically deleted within the live region.

<div
  aria-live="polite"
  aria-relevant="removals"
>
</div>

The text value informs Assistive Technologies of dynamic changes to the textual content within existing nodes within the live region.

<div
  aria-live="polite"
  aria-relevant="text"
>
</div>

The all value informs Assistive Technologies of dynamic insertion or deletion of nodes within the live region.

<div
  aria-live="polite"
  aria-relevant="all"
>
</div>

The aria-live attribute should always be present when using the aria-relevant attribute.

<div
  aria-live="[ off | polite | assertive ]"
  aria-relevant=" [ additions | removals | text | all ]"
>
</div>

aria-busy

The aria-busy attribute indicates whether an element, and its subtree, are currently being updated.

The aria-busy attribute is a state which means that needs to be changerd dynamically using JavaScript to determine the current state.

The value can be set to true when content is being loaded within the live region.

<div
  aria-live="polite"
  aria-busy="true"
>
</div>

The value can be set to false when the content loading has completed within the live region.

<div
  aria-live="polite"
  aria-busy="false"
>
</div>

The aria-live attribute should always be present when using the aria-busy attribute.

<div
  aria-live="[ off | polite | assertive ]"
  aria-busy=" [ true | false ]"
>
</div>

Any questions or comments?

5.4
Exercise: Using aria-live

Our aims are to:

  1. Add aria-live="assertive", aria-live="polite" and aria-live="off" to the message containers.
  2. Wait 10 seconds for the message to fire.
  3. Listen to the message fire using a screen reader.
<div
  id="message"
  class="error"
  aria-live="assertive"
>
</div>
<div
  id="message"
  class="warning"
  aria-live="polite"
>
</div>
<div
  id="message"
  class="info"
  aria-live="off"
>
</div>

5.5
Live region roles

Live Region roles define live regions of a document and may be modified by live region attributes.

status

The role="status" is used for content that is advisory information, but is not important enough to justify an alert.

<div
  role="status"
>
</div>

Elements set with role="status" have two implicit values.

  • Implicit aria-live="polite" - which means assistive technologies should announce updates at the next graceful opportunity.
  • Implicit aria-atomic="true" - which means the entire region should be announced when changes are detected.

For this reason, these two attributes do not be need to be defined when using role="status".

<div
  role="status"
  aria-live="polite"
  aria-atomic="true"
>
</div>

alert

The role="alert" is used for content that is important, and usually time-sensitive such as error messages.

<div
  role="alert"
>
</div>

Elements set with role="alert" have two implicit values.

  • Implicit aria-live="assertive" - which means assistive technologies should announce updates at the next graceful opportunity.
  • Implicit aria-atomic="true" - which means the entire region should be announced when changes are detected.

For this reason, these two attributes do not be need to be defined when using role="alert".

<div
  role="alert"
  aria-live="assertive"
  aria-atomic="true"
>
</div>

Any questions or comments?

5.6
Exercise: Using status and alert

Our aims are to:

  1. Add role="alert" and role="status" to the message containers.
  2. Wait 10 seconds for the message to fire.
  3. Listen to the message fire using a screen reader.
<div
  id="message"
  class="error"
  role="alert"
>
</div>
<div
  id="message"
  class="warning"
  role="status"
>
</div>

5.7
aria-invalid

The aria-invalid attribute indicates whether the entered value in a form control does not conform to the format expected by the application.

The aria-invalid attribute sets the state in the accessibility tree only. This information is then available to assistive technologies.

The false value, which is the default, means that no errors are detected.

<label for="a">First first-name</label>
<input id="a" aria-invalid="false">

The true value means that the field has failed validation.

<label for="b">Surname</label>
<input id="b" aria-invalid="true">

The grammar value means that a grammatical error has been detected.

<label for="c">Email</label>
<input id="c" aria-invalid="grammar">

The spelling value means that a spelling error has been detected.

<label for="d">Address</label>
<input id="d"aria-invalid="spelling">

Any questions or comments?

5.8
Exercise: Using aria-invalid

Files:

Our aims are to:

  1. Set 1st <input> with aria-invalid="false".
  2. Set 2nd <input> with aria-invalid="true".
  3. Set 3rd <input> with aria-invalid="grammar".
  4. Set 4th <input> with aria-invalid="spelling".
  5. Listen to each <input> using a screen reader.
<label class="label" for="firstname">
  First name
</label>
<input
  class="input"
  type="text"
  id="firstname"
  aria-invalid="false"
>
<label class="label" for="surname">
  Surname
</label>
<input
  class="input"
  type="text"
  id="surname"
  aria-invalid="true"
>
<label class="label" for="email">
  Email
</label>
<input
  class="input"
  type="email"
  id="email"
  aria-invalid="grammar"
>
<label class="label" for="address">
  Address
</label>
<input
  class="input"
  type="text"
  id="address"
  aria-invalid="spelling"
>

5.9
hidden vs aria-hidden

There is a difference between:

  • The HTML hidden attribute.
  • The ARIA aria-hidden attribute.

Elements that have the hidden attribute specified should not be displayed or receive focus.

<div hidden>
</div>

On the other hand, the aria-hidden attribute does not affect how elements or its descendants are displayed in the browser.

Element set with aria-hidden="true" are not available in the accessibility tree, and therefore, not conveyed to assistive technologies.

<div aria-hidden="true">
</div>

Any questions or comments?

5.10
Exercise: Using aria-hidden

Files:

Our aims are to:

  1. Add hidden attributes to the first paragraph.
  2. Add aria-hidden="true" to the second paragraph.
  3. Look at both elements in the accessibility tree.
<p hidden>
  Hidden content.
</p>
<p aria-hidden="true">
  Hidden from the accessibility tree.
</p>

5.11
presentation and none

The role="presentation" attribute is used to remove semantic meaning from an element and any of its child elements in the accessibility tree.

<div role="presentation">
</div>

This role can be used when an element is used to change the look of the page but does not have all the functional, or structural relevance.

For example, a <table> that is used for layout, rather than being used for tabular data should use role="presentation".

<table role="presentation">
</table>

This would cause the <table> element to be treated as if it had no role, and its semantic meaning would be removed from the accessibility tree.

However, all content contained within the <table> element would not be removed from the accessibility tree and would still be available to screen readers.

The role="none" attribute was added in ARIA 1.1 as the concept of presentation was confusing the developers. These two values operate in exactly the same way.

<table role="none">
</table>

Any questions or comments?

5.12
Exercise: Using the presentation role

Files:

Our aims are to:

  1. Add role="presentation" to the second <ul> element.
  2. Look at both elements in the accessibility tree.
  3. Listen to each of the <li> elements in both lists using a screen reader.
<ul
  class="list-style-none"
  role="presentation"
>
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
</ul>

5.13
Aria attributes that are no longer needed

The following aria-attributes are no longer needed for native form controls.

aria-disabled

The aria-disabled attribute sets the disabled state on an element in the accessibility tree only. This information is then available to assistive technologies.

<button aria-disabled="true"></button>
<button aria-disabled="false"></button>

However, as the HTML disabled attribute is so well supported across assistive technologies, there is no longer any need to use the aria-disabled attribute.

<button disabled></button>

aria-required

The aria-required attribute sets the required state on an element in the accessibility tree only. This information is then available to assistive technologies.

<input type="text" aria-required="true">
<input type="text" aria-required="false">

However, as the HTML required attribute is so well supported across assistive technologies, there is no longer any need to use the aria-required attribute.

<input type="text" required>

Any questions or comments?

Finished!