Accessibility and Older Browsers

This topic shows how to take advantage of newer features for your users who need them, and have technology that can take advantage of them, while still providing as accessible an experience as possible to your users with older technology.

Web Accessibility in Organizational Environments

The technology used to build accessible web and cloud applications is the same for intranets inside an organization or on the Internet outside an organization. However, the group of users served by the application might be quite different.

For example, when building an application for your employees, you only need to consider the IT profile of your company, given that the IT department of your organization likely supports only a limited set of operating system versions, browsers, and assistive technology products. Contrast that with the situation on the Internet, where any user with any combination of these technologies might visit your site.

Web application accessibility is a rapidly evolving area, and browser and assistive technology developers are adding new features to support web application accessibility in each new version. About 12% of computers in large commercial organizations still use Microsoft Internet Explorer 6, and if many or all of your users have older browsers or assistive technology products, you need to develop accessibility solutions in a way that works for them. At the same time, it's important to take advantage of newer features for users with newer browsers that support these technologies.

For web applications, a key technology is the Accessible Rich Internet Applications (ARIA) or Web Accessibility Initiative (WAI)-ARIA specification from the World Wide Web Consortium (W3C). At the time of this writing, ARIA is supported in Windows Internet Explorer 8 and later, Mozilla Firefox 1.5 and later, Opera 9.5 and later, and WebKit (Apple Safari 4.0 and later and Google Chrome).

Many popular commercial assistive technology products support ARIA, as do a few free ones. However, a great many older, simpler, or more niche assistive technology products do not support ARIA, or do not support it well. In determining how much your organization can rely on ARIA, you need to consider both the browsers and the assistive technology in use within your organization.

Another important consideration is whether your organization can support script. While all the major browsers have supported script since the late 1990s, those same older, simpler, and niche assistive technology products either don't support script or have poor support for script. In addition, some organizations disallow scripts for all users for security reasons.

Functional Web Accessibility

Functional web accessibility means that you begin making your user interface or controls accessible by understanding what their functions are: What does the user do with it? What are the inputs? What are the outputs? After you understand the functionality, the next step is modeling that functionality in HTML and ARIA.

In general, if there is an HTML control, such as a button, link, list (ol or ul), or form element that is close to the function of your control, you will save a great deal of development time and money by using it rather than building your own. In addition, the controls that are part of the browser have accessibility functionality built into them, which you will have to build if you create your own.

Using HTML controls and combinations of HTML controls—and following careful coding standards—creates sites that are also accessible in older browsers that do not support ARIA. Sometimes doing this requires design changes, and it is important to understand that the cost and complexity of development can increase rapidly when you build custom controls; you need to make appropriate trade-offs in design and presentation.

Step 1: Document what the user does with the control.

Step 2: Document the user input.

Step 3: Document the feedback given to the user.

Step 4: Determine whether there is an HTML control that supports the function, input and output documented in steps 1-3.

Step 5: If there is an HTML control that supports the function, input, and output, determine whether it can work in the design of the application. Otherwise, use the control plus additional ARIA, and determine whether the control plus ARIA can work in the design of the application.

Step 6: If the control cannot work in the design, can the design be changed to accommodate the control?

Step 7: If the design can be accommodated, use the control. If the design cannot be accommodated, or if there is no HTML control that supports the function, input, and output from steps 1-3, determine whether the function, input, and output can be supported by using ARIA.

Step 8: If the function, input, and output can be supported by using ARIA, build a custom control and use ARIA to make it accessible. If the function, input, and output cannot be supported by using ARIA, the control cannot be made accessible and must be redesigned. This is not a common situation.

Browsers and Assistive technology, Old and New

There are several general approaches to developing applications that work for a variety of users and configurations.

Multiple Versions

The developer creates multiple, separate sites or versions of the site. Sometimes this is called an "accessible mode" or "more accessible mode." Alternatively, users with accessibility needs might be sent to a version of the site designed for older or mobile browsers, sometimes called a "lite" or "downlevel" version.

This approach is easy to understand, but it has some drawbacks. It might not be possible to implement all the features using the technologies available to the older version. Older versions also get fewer hits, and so might get less attention and resources for testing, bug fixing, and implementation of new features than the "main" version.

Because of these two issues, some users feel that they are not getting the same experience as everyone else. And multiple versions means multiplying your cost, because each version must be developed and tested separately, and because of the added complexity of switching between versions or modes.

Graceful Degradation

The developer creates a site that uses newer features and technologies, and takes some care to have something reasonable happen when those technologies and features are not available. The assumption is that the version with the newer technologies and features is the "main" version, that not having them is an error case to handle gracefully. 

Progressive Enhancement

The developer creates a site that is fully functional without newer features and technologies, but layers on additional functionality or style in a way that makes the site better in some way, without changing the underlying functionality. This approach is similar to graceful degradation, except that it assumes that the version without the newer features is the main version, and the newer features are there only as an enhancement.

Universal Development

The developer creates a single experience that works for everyone. There are no modes, degradations, or enhancements for subsets of users. If all of the browsers and assistive technology in your organization support script and ARIA, you can create a single version that relies on these technologies and works for all of your users.

If all of your users have script enabled, but none have a browser/assistive technology combination that supports ARIA, you will use the semantics of HTML and careful scripting techniques that allow scripted sites without ARIA to work for everyone. And, if your organization prevents the use of script for all users, with and without disabilities, you can build a static site that works the same way for everyone. This approach, because it removes multiple code paths, significantly reduces development and testing cost. In addition, users prefer it because everyone gets the same functionality.

The two technologies that have the most impact on the decision of which approach to take, are script and ARIA. Script is how interactivity is added to websites for mainstream users, and ARIA is how the functionality added with script, is exposed to users of assistive technology.

SITUATION EXAMPLE APPROACH DETAILS

No script for any users

Script disabled by policy or proxy

Universal development

  • Static pages that have only links and forms

  • Accessible to all with good HTML structure

Script for most users, assistive technology that doesn't support script

Some less expensive or very old assistive technology doesn't support script

Progressive enhancement

Script executes for those that have it, but application works without it

Script for all users, no ARIA support

Employees and other users within your organization are all on Windows Internet Explorer 7 or earlier and script is not disabled by policy or proxy

Universal development

  • HTML elements

  • Semantic event handlers

  • Model complex UI in HTML

  • Simplify design where needed

Script for all users, some browser/assistive technology combinations have ARIA support

Mix of Internet Explorer 6 and Internet Explorer 8

Progressive enhancement

  • Use the same strategies as script for all users, no ARIA support

  • Layer ARIA on top

  • Test that things don't break for those without ARIA

All users have browsers and assistive technology that support ARIA

Enterprise adopts new browsers and assistive technology quickly

Universal development

  • Use HTML semantics or rely on ARIA alone

  • Custom controls marked up with ARIA

  • HTML modeling not required

  • But might be a good idea so that you can support changes in the situation without additional cost

 

Progressive Enhancement Samples

Situations with no ARIA support, with or without script, are covered fairly well in the W3C Web Content Accessibility Guidelines (WCAG) 2.0 documentation. Similarly, pure ARIA situations are covered pretty well by the ARIA Authoring Best Practices.

The following examples cover progressive enhancement to support both browsers with ARIA and those without ARIA.

Sample:  Menu Bar

HTML

The HTML for the menu bar is a list element with a few child list items, each containing a link. This is a sound semantic approach to all hierarchical, flat, or nested, groups of links, be they in a single list (toolbar), in popup child lists (menus), or in expandable lists (trees).

The menus are represented as a nested list under the second list item. Be aware that even though the second list item link has an onclick() event handler that cancels the default navigation, there is an href value for the case where script is turned off.

The WAI-ARIA roles are a role of "menubar" on the top-level ul element, a role of "menu" on the child ul elements that are pop-up menus, and a role of "menuitem" on each a href element within the menus. The aria-label property is set on the "menubar" to give it a friendly identifier for assistive technology devices, and the aria-hidden state is set on the "menu" role elements.

<ul class="menubar" role="menubar" aria-label="Navigation Bar" onkeydown="OnMenubarKeydown(event);" 
    onclick="OnMenubarClick(event);">
  <li class="first"><a role="menuitem" aria-haspopup="true" id="menu1" href="File.htm">File</a>
    <ul role="menu" aria-labelledby="menu1" aria-hidden="true" onkeydown="OnMenuKeydown(event);" 
      onclick="OnMenuClick(event);">
      <li><a role="menuitem" onkeydown="subMenuKeydown(event);" href="Open.htm">Open</a></li>
      <li><a role="menuitem" onkeydown="subMenuKeydown(event);" href="Save.htm">Save</a></li>
      <li><a role="menuitem" onkeydown="subMenuKeydown(event);" href="Print.htm">Print</a></li>
    </ul>
  </li>
  <li><a role="menuitem" aria-haspopup="true" id="menu2" href="View.htm">View</a>
    <ul role="menu" aria-labelledby="menu2" aria-hidden="true" onkeydown="OnMenuKeydown(event);" 
      onclick="OnMenuClick(event);">
      <li><a role="menuitem" onkeydown="subMenuKeydown(event);" href="Toolbar.htm">Toolbar</a></li>
      <li><a role="menuitem" onkeydown="subMenuKeydown(event);" href="Reset.htm">Reset</a></li>
      <li><a role="menuitem" onkeydown="subMenuKeydown(event);" href="Settings.htm">Settings</a></li>
    </ul>
  </li>
  <li><a role="menuitem" aria-haspopup="true" id="menu3" href="Settings.htm">Settings</a>
    <ul role="menu" aria-labelledby="menu3" aria-hidden="true" onkeydown="OnMenuKeydown(event);" 
      onclick="OnMenuClick(event);">
      <li><a role="menuitem" onkeydown="subMenuKeydown(event);" href="Account.htm">Account</a></li>
      <li>
      <a role="menuitem" onkeydown="subMenuKeydown(event);" href="Permissions.htm">Permissions</a>
      </li>
      <li><a role="menuitem" onkeydown="subMenuKeydown(event);" href="Settings.htm">Settings</a></li>
    </ul>
  </li>
</ul>

Script

The ToggleMenu() function is used to open and close the menu. After harmonizing the Mozilla and Windows Internet Explorer events, the child list element is located, its display is switched between "block" and "none", and the aria-hidden state is set to either "true" or "false". If displayed, the menu is positioned using a helper function.

function ToggleMenu(evt)
{  
  HarmonizeEvent(evt);
  evt.preventDefault();

  var src = evt.target;

  var menu = src.parentNode.getElementsByTagName("ul")[0];
  var menus = src.parentNode.parentNode.getElementsByTagName("ul");
  for (var i=0; i<menus.length; i++)
  {
  if (menu != menus[i])
    {
    menus[i].style.display = "none";
    }
  }
  if (menu)
  {
    if (menu.style.display == "block")
    {
      HideMenu(menu);
    }
    else
    {
      ShowMenu(menu,src);
    }
  }
}

CSS

The Cascading Style Sheets (CSS) for the menu bar turns off padding, margin, and list-style for the list element. The list item elements are floated left, so that they appear horizontally rather than in the default vertical list layout.

The display property on the links is set to block so that the entire tool bar item is hot. Additional CSS for the menu itself sets its position to absolute, its display to "none", and its float to "none".

/* menubar and menus */
ul.menubar, ul.menubar ul { margin:0; padding:0; list-style-type:none; }
ul.menubar li { float:left; border:1px solid; border-left:none;
  background-color:menu; color:menutext;}
ul.menubar li.first { border-left:1px solid; }
ul.menubar li a { color:black; text-decoration:none; width:100%; height:100%;
  padding:0.2em 2em 0.2em 0.5em; width:8em; display:block; }
ul.menubar a:hover { text-decoration:underline; }
ul.menubar a:focus { color:highlighttext; background-color:highlight;  }

/* menu specific */
ul.menubar ul { position:absolute; display:none; border:1px solid; }
ul.menubar ul li { float:none; border:none; }
ul.menubar ul li a { width:10em; }

For a working sample, see the Menu Bar Sample.

Sample: Tree Control

HTML

The HTML for the tree is a set of nested list elements. Be aware that the ToggleTree() event handler is bound to the a href element, and that the "+" alt attribute is on the image. In this manner, the information for the actionable link contains the alt information from the image, indicating whether the list item is expandable ("+") or collapsible ("-").

The WAI-ARIA roles are pretty straightforward for the first two, "tree" on the toplevel UL element, and "treeitem" on the node items in the tree. For the child ul elements—the hideable tree node groups—a role of "group" is assigned, because these are not new "tree" elements, but "groups" (subtrees, if you will). The most interesting of the WAI-ARIA roles, is that of "presentation" which is set on the li elements whose child a href elements get the "treeitem" role.

This role of "presentation" is required so that user agents ignore the semantic information of the li (list item) element and go straight to the child a href elements as the "treeitem" nodes. This preserves the relationship among the "treeitem" elements, which otherwise are not siblings, strictly speaking, because each is under a separate li element.

The aria-expanded state is set to indicate that the tree node is hidden. The aria-expanded state is changed in script when the element's visibility is changed.

<div id="treeBox">
<ul id="tree" role="tree" onkeydown="OnTreeKeydown(event);" onclick="ToggleTree(event);" >
  <li><a role="treeitem" aria-expanded="false" href="Documents.htm"><img height="9" 
    width="9" src="img/tree-p.png" alt="+" />Documents</a>
    <ul role="group">
      <li role="presentation"><a role="treeitem" href="File1.htm">File 1</a></li>
      <li role="presentation"><a role="treeitem" href="File2.htm">File 2</a></li>
      <li role="presentation"><a role="treeitem" href="File3.htm">File 3</a></li>
    </ul>
  </li>
  <li><a role="treeitem" aria-expanded="false" href="Photos.htm"><img height="9" 
    width="9" src="img/tree-p.png" alt="+" />Photos</a>
    <ul role="group">
      <li role="presentation"><a role="treeitem" href="Image1.htm">Image 1</a></li>
      <li role="presentation"><a role="treeitem" href="Image2.htm">Image 2</a></li>
      <li role="presentation"><a role="treeitem" href="Image3.htm">Image 3</a></li>
    </ul>
  </li>
  <li><a role="treeitem" aria-expanded="false" href="Music.htm"><img height="9" 
    width="9" src="img/tree-p.png" alt="+" />Music</a>
    <ul role="group">
      <li role="presentation"><a role="treeitem" href="Song1.htm">Song 1</a></li>
      <li role="presentation"><a role="treeitem" href="Song2.htm">Song 2</a></li>
      <li role="presentation"><a role="treeitem" href="Song3.htm">Song 3</a></li>
    </ul>
  </li>
</ul>
</div>

Script

The ToggleTree() function cancels the default action for the a href and then finds the list item's child list element. After that is found, the display of that child list element is switched, and the list item's image and alt are swapped.

function ToggleTree(evt,src)
{
  HarmonizeEvent(evt);
  evt.preventDefault();
  var node = src.parentNode.getElementsByTagName("ul")[0];
  if (node)
  {
    var img = src.getElementsByTagName("img")[0];
    if ("block" == node.style.display)
    {
      src.setAttribute("aria-expanded", false);
      node.style.display = "none";
      if (img)
      {
        img.src = "p.png";
        img.alt = "+";
      }
    }
    else
    {
      src.setAttribute("aria-expanded", true);
      node.style.display = "block";
      if (img)
      {
        img.src = "m.png";
        img.alt = "-";
      }
    }
  }
}

CSS

The CSS for the tree is fairly simple. Margins, padding, and list glyphs are turned off, and child list elements are hidden.

div#treeBox { width:15em; font-size:90%; }
ul#tree, ul#tree ul { list-style-type:none; margin:0; padding:0;
  background-color:window; color:windowtext; }
ul#tree a { color:black; text-decoration:none; display:block; display:inline-block;
  height:1.5em; padding:0.1em 1em 0.3em 0.5em; }
ul#tree a:hover { text-decoration:underline; }
ul#tree a:focus { color:highlighttext; background-color:highlight; }
ul#tree a img { border:0; vertical-align:baseline; margin-right:0.5em; }
ul#tree ul { display:none; margin-left:2em; }

For a working sample, see the Tree Control Sample.

Conclusion

This topic discusses how to design accessible web applications for browsers with and without ARIA. This topic also discusses ways to add ARIA to enhance the experience for users who have it, while still providing a good accessibility experience for those who do not. Although older browsers might require more creativity and resources to improve your users' accessible experience, it is still possible to provide an accessible experience in an environment with older technology.