Using the WAI-ARIA aria-expanded state to mark expandable and collapsible regions

From WCAG WG
This is an outdated page. The links to oaa-accessibility.org are no longer valid.
Up-to-date information is available in the ARIA Authoring Practices Guide (APG).

Status

This is an outdated page. The links to oaa-accessibility.org are no longer valid.
Up-to-date information is available in the ARIA Authoring Practices Guide (APG).
  • New technique - accepted 29 Oct 2012 pending James' additional example.
  • James to add a non-tree example.
  • Surveyed by TF 8 Oct 2012
  • 1 Nov 2012: Jason Kiss has comments on this that need to be addressed
  • David MacDonald tested the Open AJAX Alliance Example 20 linked below. WIN 7, IE 9, When focus is on "show topic 1" button, and then activated, new text is inserted into the page, but the focus is AFTER the inserted text, so presing the down arrow after inserting the new text actually takes you to the next button#2... we can't really link to that. It would need to be fixed before we do ... button #2 is ok, but button 3 and 4 miss read the same as #1. We shouldn't have focus AFTER the inserted content, when the new content is inserted. In FF14 the focus is OK but it does not announce expandable collapseable... so I agree this needs more work.

Applicability

Content using WAI-ARIA that contains expandable and collapsible regions.

This technique relates to

User Agent Notes [To be published separately]

The Open Ajax Alliance treeview example does not work with VoiceOver in Safari.

Description

The objective of this technique is to use the aria-expanded state to indicate whether regions of the content are collapsible, and to expose whether a region is currently expanded or collapsed. As an example, when subtrees of a tree can be expanded and collapsed dynamically, the aria-expanded state indicates whether the subtree can be expanded or collapsed, as well as whether or not it is currently expanded or collapsed.

This attribute can be used with elements of the following roles: alert, alertdialog, application, article, banner, button, columnheader, combobox, complementary, contentinfo, definition, dialog, directory, document, form, grid, gridcell, group, heading, img, link, list, listbox, listitem, log, main, marquee, math, menu, menubar, navigation, note, presentation, radiogroup, region, row, rowgroup, rowheader, search, separator, status, tab, tablist, tabpanel, timer, toolbar, tooltip, tree, treegrid, treeitem.

Examples

Example 1: Using a button to collapse and expand a region

A button hides or exposes a paragraph of text on the page. The state of the paragraph is represented by the attribute aria-expanded on the button..

The following snippet from The Open Ajax Accessibility Examples, Example 20, shows WAI-ARIA mark-up for a button that shows or hides some text. Note that the JavaScript sets the attribute aria-expanded and manages the styling of collapsed paragraphs so they are not visible.

<p class="button">
    <button id="button1" class="buttonControl" aria-controls="t1" aria-expanded="false"><span>Show</span> Topic 1</button>
</p>

<div id="t1" class="topic" role="region" tabindex="-1" >
    Topic 1 is all about being Topic 1 and may or may not have anything to do with other topics.
</div>

CSS snippet for the topic text. Note display:none hides this element. Showing the element will change this attribute.

div.topic {
    display: none;
    margin-bottom: 1em;
    padding: .25em;
    border: black thin solid;
    background-color: #EEEEFF;
    width: 40em;
}

The following Javascript snippet demonstrates the updating of the aria-expanded property as the region is hidden or shown. The function slideToggle does the work of changing the element's visibility.

hideShow.prototype.toggleRegion = function() {

      var thisObj = this;

    // toggle the region
    this.$region.slideToggle(this.toggleSpeed, function() {

      if ($(this).attr('aria-expanded') == 'false') { // region is collapsed

        // update the aria-expanded attribute of the region
        $(this).attr('aria-expanded', 'true');

        // move focus to the region
        $(this).focus();

        // update the button label
        thisObj.$toggle.find('span').html('Hide');

      }
      else { // region is expanded

        // update the aria-expanded attribute of the region
        $(this).attr('aria-expanded', 'false');

        // update the button label
        thisObj.$toggle.find('span').html('Show');
      }
    });

} // end toggleRegion()

This example is available as part of the working example of Example 20 - Hide/Show: Region follows button, on the OpenAjax Alliance site.

Example 2: Collapsing and expanding subtrees of a tree

A widget with role tree can allow a user to expand or collapse subtrees of the tree. The widget author is responsible for providing the operations to expand or collapse a subtree. The state of the tree_item is represented by the attribute aria-expanded.

The following snippet from The Open Ajax Accessibility Examples, Example 41, shows WAI-ARIA mark-up for a tree widget that manages collapsing and expanding groups in JavaScript. The JavaScript sets the attribute aria-expanded and manages the styling of collapsed groups so they are not visible:

<ul id="tree1" class="tree root-level" role="tree" aria-labelledby="label_1">
   <li id="fruits" class="tree-parent" role="treeitem" tabindex="0" aria-expanded="true">
      <span>Fruits</span>
      <ul id="fruit-grp" role="group">
         <li id="oranges" role="treeitem" tabindex="-1">Oranges</li>
         <li id="pinapples" role="treeitem" tabindex="-1">Pineapples</li>
         <li id="apples" class="tree-parent" role="treeitem" tabindex="-1" aria-expanded="false">
            <span>Apples</span>
            <ul id="apple-grp" role="group">
               <li id="macintosh" role="treeitem" tabindex="-1">Macintosh</li>
               <li id="granny_smith" class="tree-parent" role="treeitem" tabindex="-1"
                      aria-expanded="false">
                  <span>Granny Smith</span>
                  <ul id="granny-grp" role="group">
                     <li id="Washington" role="treeitem" tabindex="-1">Washington State</li>
                     <li id="Michigan" role="treeitem" tabindex="-1">Michigan</li>
                     <li id="New_York" role="treeitem" tabindex="-1">New York</li>
                  </ul>
               </li>
               <li id="fuji" role="treeitem" tabindex="-1">Fuji</li>
            </ul>
         </li>
         <li id="bananas" role="treeitem" tabindex="-1">Bananas</li>    
         <li id="pears" role="treeitem" tabindex="-1">Pears</li>    
      </ul>
   </li>
</ul>

The following excerpt from the JavaScript for this example expands the items in a group. The expand/contract image is updated to reflect the operation that is now available for this group.

treeview.prototype.expandGroup = function($item, hasFocus) {

  var $group = $item.children('ul'); // find the first child ul node

  // expand the group
  $group.show().attr('aria-hidden', 'false');

   // set the aria-expanded property
  $item.attr('aria-expanded', 'true');

  if (hasFocus == true) {
    $item.children('img').attr(
          'src', 'http://www.oaa-accessibility.org/media/examples/images/expanded-focus.gif')
       .attr('alt', 'Group expanded');
  }
  else {
    $item.children('img').attr(
         'src', 'http://www.oaa-accessibility.org/media/examples/images/expanded.gif')
        .attr('alt', 'Group expanded');
  }

  ...

} // end expandGroup()

The following excerpt from the JavaScript for this example collapses the items in a group. The expand/contract image is updated to reflect the operation that is now available for this group.

treeview.prototype.collapseGroup = function($item, hasFocus) {

  var $group = $item.children('ul');

  // collapse the group
  $group.hide().attr('aria-hidden', 'true');

   // update the aria-expanded property
  $item.attr('aria-expanded', 'false');

  if (hasFocus == true) {
    $item.children('img').attr(
         'src', 'http://www.oaa-accessibility.org/media/examples/images/contracted-focus.gif')
      .attr('alt', 'Group collapsed');
  }
  else {
    $item.children('img').attr(
         'src', 'http://www.oaa-accessibility.org/media/examples/images/contracted.gif')
       .attr('alt', 'Group collapsed');
  }

  ...

} // end collapseGroup()

This tree is available as part of the working example of Example 41 - Tree View, on the OpenAjax Alliance site.

Example 3: Omitting aria-expanded produces a static tree

The WAI-ARIA Primer demonstrates a tree widget. Note the use of the roles "tree", "treeitem", and "group" to identify the tree and its structure. Here is a simplified excerpt from the code.

This example does not support expanding or collapsing subtrees, so the attribute aria-expanded is omitted, which indicates that the element it controls is neither expandable nor collapsible. All the element's direct child elements (if any) are shown.

<ul role="tree" tabindex="0">
  <li role="treeitem">Birds</li>
  <li role="treeitem">Cats
    <ul role="group">
      <li role="treeitem">Siamese</li>
      <li role="treeitem">Tabby</li>
    </ul>
  </li>
  <li role="treeitem">Dogs
    <ul role="group">
      <li role="treeitem">Small Breeds
        <ul role="group">
          <li role="treeitem">Chihuahua</li>
          <li role="treeitem">Italian Greyhound</li>
          <li role="treeitem">Japanese Chin</li>
        </ul>
      </li>
      <li role="treeitem"">Medium Breeds
        <ul role="group">
          <li role="treeitem">Beagle</li>
          <li role="treeitem">Cocker Spaniel</li>
          <li role="treeitem">Pit Bull</li>
        </ul>
      </li>
      <li role="treeitem">Large Breeds
        <ul role="group">
          <li role="treeitem">Afghan</li>
          <li role="treeitem">Great Dane</li>
          <li role="treeitem">Mastiff</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

Resources

Related Techniques

Tests

Procedure

For a user interface component with a WAI-ARIA role attribute that supports the aria-expanded attribute:

  1. If the groups of items can be expanded and collapsed, and is currently expanded, check that the aria-expanded attribute is to true on the triggering element.
  2. If the groups of items can be expanded and collapsed, and is currently collapsed, check that the aria-expanded attribute is to false on the triggering element.
  3. If the group of items cannot be expanded or collapsed, check that the aria-expanded attribute is not set.
  4. Check that the attribute value is updated to reflect the current state when the group changes state.

Expected Results

  • All checks are true