Sunday, August 22, 2010

Making your menus accessible is really easy

WAI-ARIA, the Accessible Rich Internet Applications Suite, defines a way to make Web content and Web applications more accessible to people with disabilities. It especially helps with dynamic content and advanced user interface controls developed with AJAX, HTML, JavaScript, and related technologies. Currently certain functionality used in Web sites is not available to some users with disabilities, especially people who rely on screen readers and people who cannot use a mouse (e.g mobile devices users). WAI-ARIA addresses these accessibility challenges, for example, by defining new ways for functionality to be provided to assistive technology. (http://www.w3.org/WAI/intro/aria)

So, trying to make our content more accessible is a pretty important step in web development. By including roles, states and properties, ARIA helps us make our code semantically richer for the assistive technology user. ARIA enables semantic description of an element or widget behavior and enables information about groups and the elements within them. ARIA states and properties are accessible via the DOM.

A common use case is a navigation menu. Almost every site/blog out there has a tabbed navigation menu. How could we make these menus more accessible..? It just takes few attributes in our dom elements, such as "role".

The ARIA "role" attribute

The role attribute enables us to create semantic structure on elements. Two notes about roles:
  1. once set, a role should not be dynamically changed, since this will confuse the assistive technology
  2. roles take precendence over element default semantic meaning

Menu Example

Here is a simple menu we see in many sites:
<div class="topMenuWrapper"> 
 <div class="topMenuWrapperInner"> 
  <ul class="topMenuList"> 
   <li class="topMenuListItem">
     <a href="#"><span class="menuItemContent">Menu item 1</span></a>
   </li>
   <li class="topMenuListItem">
     <a href="#"><span class="menuItemContent">Menu item 2</span></a>
   </li> 
   <li class="topMenuListItem">
     <a href="#"><span class="menuItemContent">Menu item 3</span></a>
   </li> 
   <li class="topMenuListItem">
     <a href="#"><span class="menuItemContent">Menu item 4</span></a>
   </li> 
  </ul> 
 </div>
</div>
By the way, here is the CSS to make a working example, with horizontal tabs:
body {
   background-color: #F8F8F8;
}

.topMenuWrapperInner {
   margin: 5em;
   float: right;
}

.topMenuList {
   margin: 0px; 
}

.topMenuListItem {
   margin-right: 10px; 
   padding: 6px;
   display:inline;
   background-color: #ddd;
   border: 1px solid #ddd;
  /* lets add rounded corners for real browsers :P */
   -webkit-border-top-left-radius:5px;
   -webkit-border-top-right-radius:5px;
   -moz-border-radius-topleft:5px;
   -moz-border-radius-topright:5px;
}

.topMenuListItem a {
   color: #fff;
   text-decoration: none;
   font-weight: bold;   
}

.topMenuListItem:hover {
   background-color: #fff;
   border: 1px solid #ddd;
}

.topMenuListItem:hover a {
   color: #B0B0B0;
}

.menuItemContent {
   padding:10px;
} 
Now let's make our top menu accessible:
<div class="topMenuWrapper"> 
 <div role="menu" class="topMenuWrapperInner"> 
  <ul role="presentation" class="topMenuList"> 
   <li role="presentation" class="topMenuListItem">
     <a href="#" role="menuitem">
      <span class="menuItemContent">Menu item 1</span>
     </a>
    </li>
    <li role="presentation" class="topMenuListItem">
     <a href="#" role="menuitem">
      <span class="menuItemContent">Menu item 2</span>
     </a>
    </li> 
    <li role="presentation" class="topMenuListItem">
     <a href="#" role="menuitem">
      <span class="menuItemContent">Menu item 3</span>
     </a>
    </li> 
    <li role="presentation" class="topMenuListItem">
     <a href="#" role="menuitem">
      <span class="menuItemContent">Menu item 4</span>
     </a>
    </li> 
   </ul> 
 </div>
</div>
Now let's see what each attribute means:
  1. role = menu: Offers a list of choices to the user.
  2. role = presentation: An element whose role is presentational does not need to be mapped to the accessibility API.
  3. role = menuitem: A link in a menu. This is an option in a group of choices contained in a menu.
As I mentined above, its pretty easy to make our sites accessible. One nice side effect is that if you also use suggested ARIA practices, you can make your site faster to navigate with the keyboard, which benefits all users. If you are using frameworks to build your own menus, be sure to use ones that provide WAI-ARIA support, such as:
  1. YUI3: MenuNav Node Plugin
  2. Tabs - JQuery accessible RIA
If you are interested in exploring ARIA further, here are some pretty usefull resources:
  1. WAI-ARIA Best Practices, http://www.w3.org/TR/2008/WD-wai-aria-practices-20080204/
  2. WAI-ARIA Roles, http://www.w3.org/TR/wai-aria/usage#usage_intro

2 comments:

  1. With all the extra text we have to add to our HTML tags and the relative inconvenience of generating that extra text gracefully, someday we wont even write HTML, it'll all be generated by libraries or IDEs...

    ReplyDelete
  2. @Julian Sure, I agree...eventually someone will come up with an automated way to do this job for us...but till then we should try to make our sites as much as possible globally accessible. :)

    ReplyDelete