Make your HTML/JavaScript app accessible

One of the hallmarks of a Windows 8 app is that accessibility is built into the platform. You can use accessibility features to widen the reach of your app with very little effort. We have received positive feedback on this approach from both developers and users and have refined the platform. Now we walk you through how to think about accessibility in your HTML and JavaScript apps during the design phase, show how to implement and test accessibility for some of the common UI patterns, provide some best practices we used when creating custom UI controls, and discuss the opportunity you have in reaching the full spectrum of Windows users by addressing accessibility.

The info and samples in this blog are specific to HTML/JavaScript, but we built accessibility into XAML apps too. You can use the templates and controls that the development tools provide, and reference the guidance and practices to avoid available on the Dev Center to help you create your accessible XAML apps.

Accessibility matters

In building Windows 8, we wanted to empower all users to benefit from the rich app ecosystem and enrich their daily lives with amazing accessible apps. This is why we built accessibility into the Visual Studio templates, IntelliSense, common controls, and provided testing tools and a way to declare the app as accessible. Enabling accessibility in your app is important as it impacts about 15% of the world’s population. We want you to be able to reach this user base and to adopt some of the best practices that we use internally for our own apps. These practices are a great starting point in making your app accessible. In this post, you will learn how to:

  1. Identify the accessibility scenarios and how to easily support them in your app.
  2. Use the platform controls as there is a lot of built-in accessibility that you get for free.
  3. Determine whether your app meets accessibility requirements.
  4. Plan for accessibility testing, use the SDK tools (Inspect and UI Accessibility Checker), focus on enabling scenarios for users who require the use of screen reader, who only use the keyboard, and/or need to change the contrasts or scaling.
  5. Learn how the Store accessibility declaration works and how it can help you reach more users.

By following the best practices, you will not only understand how a user with disabilities experiences your app, but also develop an app that meets the needs of a broader range of users.

Essentials of accessible apps

Apps consist of essential elements like tiles, app bars, ListViews, and navigation. Let’s look at these elements and see how easy it is to make them accessible.

Tiles

Tiles represent your app in the Start screen and are the first thing the user experiences about your app. Tilesare accessible by default for the screen reading experience! And to enable the High Contrast experience, you only need to add High Contrast versions of your tiles to your Visual Studio project.

logo contrastblacklogo contrastwhitelogo

/ProjectFolder

/images/

logo.png

/contrast-black

logo.png

/contrast-white

logo.png

/ProjectFolder

/images

logo.png

/contrast-black

logo.png

/contrast-white

logo.png

/ProjectFolder

/images

logo.png

/contrast-black

logo.png

/contrast-white

logo.png

Figure 1. Music, Video and Xbox LIVE Games tiles support High Contrast Black and White themes. The boldface font identifies the version of the tile above it.

Additionally, you can enable more users with vision impairments by setting the text foreground and background colors to meet a 4.5:1 contrast ratio. You can verify the contrast ratio by comparing foreground and background color codes using one of the W3C recommended tools (dark= #2A2A2A, light=#FFFFFF).

vs_manifest
Figure 2. Visual Studio manifest settings for tile logo text.
Only the resulting Tile text on the left has sufficient text contrast.

Ensuring a great High Contrast experience and sufficient logo text contrast for your tiles will make your app more attractive to users with visual impairments.

App bars

App bars provide quick and easy access to commands related to apps, so they need to be accessible.

Just like tiles, the app bar commands are accessible by default if you use the standard HTML controls. For example, if you are using platform Button controls, like in the markup here, your commands will be fully accessible by defaultwithout any additional work!

Example 1: Markup for the standard bottom app bar. There are no special accessibility attributes, everything is built in.

 <div id="appbar" data-win-control="WinJS.UI.AppBar">
        <button 
data-win-control="WinJS.UI.AppBarCommand" 
data-win-options="{id:'cmdAdd',label:'Add',icon:'add', section:'global'}">
       </button>
       <button           
                data-win-control="WinJS.UI.AppBarCommand" 
data-win-options="{id:'cmdRemove',label:'Remove',icon:'remove', section:'global'}">
        </button>
        <hr data-win-control="WinJS.UI.AppBarCommand" 
data-win-options="{type:'separator',section:'global'}" />
        <button          
data-win-control="WinJS.UI.AppBarCommand" 
data-win-options="{id:'cmdDelete',label:'Delete',icon:'delete',section:'global'}" >
       </button>
</div>

app bar combined

Figure 3. App bar is accessible by default and supports screen reading, keyboard-only use, high contrast and text contrast.

Using the app bar to expose frequently used commands makes them easily accessible for visually impaired users. For example, in the Music app that we developed, the playback controls in the app bar are accessible and read out by screen readers like Narrator.

music app

Figure 4: Music app play controls in app bar allowing quick and easy access.

Similar to tiles, ensure that your app bar elements support high contrast and that the colors you choose meet the text contrast requirements.

ListView controls

A ListView (as shown in Figure 5) is one of the most common WinJS controls. It offers a rich experience for viewing and managing data collections. Just as the other platform controls we’ve discussed, the ListView is fully accessible by default!

list views

Figure 5: List Views are frequently used in apps.

The next markup from the Visual Studio 2012 Grid App template demonstrates setting accessibility attributes for the ListView control. It shows how to:

  • Set the accessible name with aria-label for the ListView control.
  • Define the list item template data binding: map IMG Alt attribute to the data source title column.

Note that list items’ accessible names are set by default, based on the list item text content.

Example 2: Visual Studio 2012 Grid app template is accessible. Highlighted attributes are set for accessibility.

 <!-- These templates display each item in the ListView declared here. -->
<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
    <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
    <div class="item-info">
        <h4 class="item-title" data-win-bind="textContent: title"></h4>
        <h6 class="item-subtitle " data-win-bind="textContent: subtitle"></h6>
        <h4 class="item-description" data-win-bind="textContent: description"></h4>
    </div>
</div>
<!-- The content that will be loaded and displayed. -->
<div class="fragment groupeditemspage">
    …
    <section aria-label="Main content" role="main">
        <div class="groupeditemslist" 
aria-label="List of groups" data-win-control="WinJS.UI.ListView" 
            data-win-options="{ selectionMode: 'none' }">
        </div>
    </section>
</div>

vs grid

Figure 6: Accessible Visual Studio 2012 Grid app project template showing the accessibility properties within the SDK tool Inspect.

After setting the accessibility attributes, ensure that the content of your list items supports high contrast and that the colors you choose meet text contrast requirements.

Efficient keyboard navigation

Keyboard navigation is essential for several reasons. Enthusiasts still rely on the keyboard to power use Windows and there is a segment of the Windows users that rely solely on the keyboard for navigating and using the system. Users with visual, mobility, or dexterity impairments depend on keyboard support to use their computers. When you design your app, factor in efficient and good keyboard navigation support for these users.

The good news: we have made it easy to support keyboard navigation too. All platform controls have keyboard navigation already built-in! All interactive elements are in tab order by default and container elements, like ListView, implement inner arrow key navigation so that you can use arrow keys to go through the list. Using platform controls gets you a lot of accessibility for free, including efficient keyboard navigation.

list view arrows

Figure 7: Small number of tab stops and built-in ListView arrow keys navigation makes Mail app keyboard navigation efficient.

One interesting question that came up when we were designing our apps that you may encounter was “Do I need to add text elements to the tab order to get screen readers to read them?”

The answer is no. Static text should not be in the tab order because it is already exposed by the platform already exposes it in the UI Automation (UIA) tree and that is how it is accessible to screen readers. Narrator and other screen readers have reading commands (for example Caps + M which reads text from the Narrator cursor position) and UIA tree navigation commands (Caps + left/right arrow) for reading all UIA tree elements sequentially. Therefore, you don’t need to add an extra tab element for them.

Make your custom UI accessible

In the previous sections, we looked at the benefits of the built in accessibility when you use the standard controls. But for complex apps, you may need to build a custom UI. Here are some tips based on our experiences that can help you make your UI accessible.

Describing custom UI for accessibility

When you build accessible custom UI with HTML/JavaScript, also read the Accessbile Rich Internet Application (ARIA) standards by the W3C to understand the available ARIA roles and properties. This in addition to the guide on making your apps accessible on the Dev Center can help you make the right choices when modeling your UI and setting accessibility properties. Let’s go through some common patterns of custom UI and what we did in our apps to make them accessible. By following our tips and the information in the guides, you can easily adopt accessibility for your custom UI implementations.

Controlling content with tab lists

The Travel app, which is available in the release preview, uses custom UI for the flight search form. While this UI is fairly complex, making it accessible was straightforward. We did this by setting the attributes: role, aria-controls and aria-selected.

Start by choosing the correct pattern

Instead of using buttons for the Search, Schedule and Status elements, we decided to describe the entire Flight search form in the Travel app as an ARIA tablist for navigation and it allowed us to provide more info. The tablist contained the Search, Schedule and Status elements as ARIA tabs, with ARIA-selected attribute to reflect currently selected tab, and ARIA-controls attribute to point to the related content. This approach allowed us to provide the users with more info about the UI and a richer accessible experience.

Example 3: Bing Travel app, Flight Search, using tablist and tab elements.

 <div class="…" role="tablist">
    <div … id="flightSearchTripTab" role="tab" aria-controls="flightSearchTripView">
        …
    </div>                                
    <div … id="flightSearchFlightSchedulesTab" role="tab" aria-controls="flightSearchFlightSchedulesView">
        …
    </div>
    <div … id="flightSearchFlightStatusTab" role="tab" aria-controls=" flightSearchFlightStatusView">
        …
    </div>
</div>
…
<!-- Trip view-->
<div … role="tabpanel" role="tabpanel" id="flightSearchTripView"> … </div>
<!-- Flight status view-->
<div … role="tabpanel" id="flightSearchFlightSchedulesView"> … </div>
<!-- Flight status view-->
<div … role="tabpanel" role="tabpanel" id="flightSearchFlightStatusView"> … </div>

_showTabView: function (tab) {
    …
    if (tabElement) {
        WinJS.Utilities.removeClass(tabElement, "flightSearchUnselectedTab");
        WinJS.Utilities.addClass(tabElement, "flightSearchSelectedTab");
        tabElement.setAttribute("aria-selected", "true");
    …
    }
    …
}

sdktools

Figure 8: The SDK tool, Inspect, showing the accessibility data for the tablist and tab elements for the Bing Travel app.

If you use ARIA-controls in your app to expose info about the relationship between tab elements and the content they are controlling, users will be able to use the Narrator Jump command for moving focus to a tab with linked content (using Caps + Insert keys).

Selecting tabs programmatically

To enable the Travel app Search form to work seamlessly with Narrator on touch only devices, we needed to allow users to select tab elements programmatically (Caps + Space or double tap with Narrator).

We did this by describing the Search, Schedule and Status as ARIA tabs, which resulted in the platform exposing them as the UIA SelectionItem control pattern. In turn, the Narrator double tap gesture changes the ARIA-selected property for these tab elements. So, to ensure the correct content is loaded for the selected tab, we also needed to add a propertychange event handler for the tab’s ARIA-selected attribute. Here’s the example:

Example 4: Handle onpropertychange for ARIA-selected property to detect programmatic change of tab selection.

 tabElement.attachEvent("onpropertychange", selectionChanged);

function selectionChanged(event) {
        if (event.propertyName === "aria-selected")
if (event.srcElement.getAttribute("aria-selected") === "true") {
    // execute code to load the content that corresponds with the selected tab element 
} else {
// execute code for deselected tab, if needed
        }

}

       

When we talk about controlling UI programmatically, there is another topic you need to consider to ensure the Narrator touch experience is supported. That is the accessible touch events.

Accessible touch events

Considering that Windows 8 experience is designed as a touch first environment, we recommend that you use touch events for a smooth UI flow and touch performance.

If you only use the touch events MSPointerUp and MSPointerDown, you need to handle Click events to support accessibility experiences with screen readers. This allows Narrator, as an example, to interact with your UI programmatically using Caps + Space or double tap. One way you can do this is to encapsulate the MSPointerUp event handler code into a separate function and call that same function (delayedPointerUp) form Click event handler. Here’s an example of how we did this in on of the Bing apps (code simplified):

Example 5: Solution for making touch events programmatically accessible and enabling Narrator touch experience.

 Bing apps, platform\js\utilities.js:
element.addEventListener("click", onClick);
element.addEventListener("MSPointerUp", onMsPointerUp);
…
var pointerUpEventObject = null;
var pressedElement = null;
var isClick = false;

function onClick(evt) {
    isClick = true;
    delayedPointerUp();
}

function onMsPointerUp(evt) {
    pointerUpEventObject = evt;
    msSetImmediate(delayedPointerUp);
}
…
function delayedPointerUp() {
    if (isClick || pointerUpEventObject && 
            (pointerUpEventObject.srcElement == pressedElement || … right button checks…)) {
        pointerUpEventObject = null;
        isClick = false;
        invokeItem(pressedElement);
    }
}
…

To prevent the delayedPointerUp from being executed twice for a mouse click, which will trigger both Click and onMsPointerUp, you can:

  • Use msSetImmediate to postpone MSPointerUp call of delayedPointerUp
  • Use pointerUpEventObject variable to keep the reference to MSPointerUp event object
  • Use isClick variable to track if Click handler was executed
  • Prevent the second execution of delayedPointerUp by resetting isClick and pointerUpEventObject variables after the first execution of delayedPointerUp.

By adding these few lines of code, you will enable the Narrator touch experience so that the double tap gesture programmatically activates the functionality associated with the interactive elements in your UI.

Auto-completion

Another example of a custom feature we did in the Mail app that works well with screen readers like Narrator is the auto-completion found in the address control.

The idea behind the auto-completion solution for Mail address control (addressbarToField) is to display one list (toDDDDList) for the address suggestions and the another list (toL) for storing the chosen contacts. To make this accessible, we set the input field (toIF) role attribute to a combobox to reflect that it had a related drop down list. We also set the input field (toIF) ARIA-controls attribute to point to the suggestions list, which shows as the user starts typing. This allows Narrator to announce the selection events for the suggestions list (toDDDDList), while the keyboard focus remains in the main input field (toIF). Here is how we did this:

Example 6: Mail app address field accessibility solution for auto-complete.

 <div id=" addressbarToField" class="…">
<div id=" toOC" class="…">
              <div id="toL" role="listbox" ><!--chosen contacts--></div>
<input id="toIF" size="1" type="email" role="combobox" aria-autocomplete="list"
aria-controls="toDDDDArea" aria-activedescendant="toDDList0" />
</div>
<div id="toDDDDArea" role="group" class="…">
          <div id=" toDDDDList" role="listbox">
        <div id="toDDList0" role="option" aria-selected="true">…</div>
        <div id="toDDList1" role="option" aria-selected="false">…</div>
…
</div>    
</div>
</div>

The autocompletion solution enables the user to type in the input field, the list of suggestions appear, and Narrator announces the first selected contact. As the user continues to type, the suggestions list is reduced causing a new selection event to be fired, which again prompts Narrator to announce the new top contact element in the list. If the user uses the keyboard’s arrow keys to move up and down the suggestions list, Narrator continues to announce the selected contacts. At all times the keyboard focus remains in the input field.

narrator

Figure 9: Narrator reads suggestions as list changes, Inspect shows UIA info exposed with ARIA (activedescendant, controls)

Accessible graphical elements

Graphical elements have always been a challenge for accessibility because there is no straightforward way of making them accessible. At a minimum, set an accessible name and role (usually to ARIA img) for such elements so that users who use a screen reader know that these elements are on the screen. If these graphical elements are interactive, the user needs to have a way to navigate them.

On the other hand, if you can make an interactive graphical element accessible, it can be effective and may attract positive customer feedback. One good example is the Bing Weather app and its Historical Weather chart. It is accessible for Narrator keyboard scenarios and High Contrast themes. We did this by exposing each month in the chart as separate UIA tree elements with accessible names. We added the ARIA-described by pointer to the month’s historical info displayed next to the chart on the right. As the user arrows left or right the months highlight moves and Narrator announces the month’s name and then reads the month’s historical info. Here is the code snippet:

Example 7: Bing Weather app, dynamically setting ARIA-described by to the currently selected month element.

 SetArrowKeyHandler: function (parentNode, chartObject) {
        …
            for (var index = 0, len = tickLabels.length; index < len; index++) {
                tickLabels[index].addEventListener("keydown", function (event) {
            …
                    if (newMonth) {
                        newMonth.focus();
                        newMonth.tabIndex = "0";
                        newMonth.,setAttribute("aria-describedby", "hwModuleShifted");
                        hwChart.HandleMonthClick(newMonthIndex, chartObject);
                        this.blur();
                        this.tabIndex = "-1";
                        this.removeAttribute("aria-describedby");
                    }

                });
            }
        }

bing chart

Figure 10: Bing Weather, Historical Weather chart – arrow keys navigation allows Narrator to read month info.

Referencing elements with ARIA

If you use ARIA relationship attributes like ARIA-controls or ARIA-described by to reference other elements, make sure that the target elements must be recognized by the platform as UIA objects. You can verify this by using Inspect to locate that element in the UIA tree. That is unless it is explicitly hidden from the tree with ARIA-hidden=”true” or by setting its style to be visually hidden.

In the next example, the referenced “A” DIV tag is not participating in the INPUT field accessible name, nor is it in the UIA tree because DIV tags are not considered as a UIA object by default. In contrast, “B” DIV tag is participating in the INPUT field name and is present in UIA tree because it has a role attribute set.

Example 8: Referenced DOM elements must be regular UIA object represented in UI tree or explicitly hidden from it.

 <input type="text" aria-labelledby="idA idB" /><div id="idA">A</div><div id="idB" role="heading">B</div>
dom elements

Testing scenarios for accessibility

The goals when testing apps for accessibility are to ensure users can experience your app no matter their abilities. This means testing each UI element in your app for accessibility, verifying that users can accomplish each of the app’s tasks end-to-end with Narrator (using both keyboard and touch), in High Contrast (black and white), and with Make everything bigger (see the Ease of Access setting under Settings -> Change PC Settings).

Testing with Narrator is very helpful as it reads and interacts with your UI by relying on the UI Automation API, which supports the ARIA standards we have covered earlier. On touch only devices, Narrator allows you to inspect UI by moving your finger over UI elements and use gestures to move keyboard focus, navigate the UIA tree, invoke or select elements, read text content in different modes, and more.

Reaching more users with Store accessibility declaration

After you create and test your accessible app using some of the examples we’ve provided in this blog, and follow the accessibility guidelines, you can declare your app as accessible! This means that it can be used by a broader set users compared to other apps that didn’t consider accessibility.

To get credit for your work and to expand your user base, declare your app as accessible by checking the accessibility checkbox during the publishing process.

windows store

Figure 11: The Windows Store onboarding page displaying the option to check the box if the app is accessible.

If you declare your app accessible, users can filter on this by selecting it in their preferences. This way they can quickly find apps that they are able to use with with screen readers, make everything bigger or use high contrast settings.

Conclusion

The time you put into making your apps accessible is a valuable investment that will extend the reach of your app to a broader user base and improve the quality of your app. A lot of this work is already done for you when you use the standard controls that are accessible by default. But if you need to add more complex experiences or custom UI, follow the best practices we provided here and the reference materials to make your app accessible.

--Jennifer Norberg Lead Program Manager