I’ve been playing around a bit with Dojo Mobile. My goal is to relearn Dojo and to build an accessible Web app for iOS. Unfortunately not all of the Dojo Mobile components are fully accessible, yet (the team is working on it). The app I am building is fairly simple – an app to track a user’s step count from a pedometer. An app of this type is a bit moot since there are sophisticated devices that do this and communicate to an app via Bluetooth. However, this app uses some basic constructs so it seemed like a real-world but simple undertaking.
For those who don’t know, VoiceOver is the screen reader from Apple that works with iOS devices. There is also a version for OS X. VoiceOver allows blind, low vision and mobility impaired people to use iOS devices either with or without a keyboard. There are many more accessibility features in iOS as well.
A Simple, Scrollable Region
In order for a user to examine her history of recorded steps I need to use a list within a scrolling view. The header and bottom toolbar are locked on the screen and the user can scroll through the data.
The ScrollView provided as part of Dojo Mobile works great and was easy to implement. It works as expected for sighted users who can visually interact with the app. However, one of my goals is to make a fully accessible app and the ScrollView is not accessible to the VoiceOver screen reader. The team is working to make it accessible for the next Dojo release (1.9.1) but I decided to try and come up with some work arounds. Now that iOS and Mobile Safari support the overflow:auto CSS feature, this seems like the logical choice.
I found this example on how to use overflow:auto to create a scrolling div within a fixed header and footer on the page: http://techtalk.virendrachandak.com/sticky-header-and-footer-using-css/. This uses a div of scrolling paragraphs rather than a list and does work well with VoiceOver on my iPhone 4S. I spent a little more time simulating my situation of a list and came up with an example using a list that mimics the iOS ListView.
Fixing the Header and Footer
The header and footer need to be fixed at the top and bottom of the page so the contents can scroll between them. The following styles are used to fix the header and footer to the top and bottom of the page, respectively:
There is some visual fluff here but the important pieces are the first 5 lines – fixing the position and top as well as specifying the height. The same is true for the footer (with bottom rather than top included):
Scrolling the Contents
Note that the top and bottom padding matches the height of the fixed header and footer. Now the contents of the block element assigned the scrollContainer class will scroll as expected between the header and footer when dragging your finger on the screen.
Adding Scrolling Data
I hard coded some simple data to represent logging of steps during the month of June. The date and the number of steps make up each list item. The list is implemented using ul and li elements with appropriate styling. I just made the step count increment by 1 each day so it corresponded with the date: June 1 has 1001 steps, June 2 has 1002 steps etc. For those of us not used to it, listening to VoiceOver can be very tedious. I want to make sure items are scrolling properly and listening to incremental data is helpful. Even if I don’t listen to the entire list item being spoken I have some idea where I am in the list. Although it would have been better if I had typed out the date, June 1 for instance, rather than 06/01 because VoiceOver speaks them both together. It is a bit confusing to hear, “zero six slash zero one one zero zero one button” for each entry.
Each list item is given a role of button. The idea is that you tap an item to open a new screen with additional details. There is no event handler for the button in this code so activating it does NOT work. The idea is to demonstrate the scrolling not the fully implemented app! When the list item is not marked as a button, the two pieces of information, the data and the step count, are focused and spoken separately by VoiceOver. By adding the role of button they are focused and spoken as one unit. Here is the code for the scrolling section:
<div id="container" class="scrollContainer">
<ul class="stepData" style="padding:0px;">
<li role="button">06/01<span class="rightData">1001</span></li>
<li role="button">06/02<span class="rightData">1002</span></li>
// rest of month data goes here …
<li role="button">07/08<span class="rightData">1038</span></li>
<li role="button">07/09<span class="rightData">1039</span></li>
Testing with VoiceOver
If you run this example on an iOS 6 iPhone running VoiceOver it works pretty well. Here is the url so you can cut and paste if necessary: http://www.weba11y.com/Examples/overflow/overflowListSimple.html.
I am not a VoiceOver expert but here are the ways I found to move through the list items.
- Swipe left and right to move from backwards and forwards from list item to list item.
- Slide your finger down the screen to move down the list from item to item. However when you reach the last visible list item the footer will receive focus even though you are not at the end of the list.
- Slide your finger up to move up the list. The same problem occurs at the top of the screen area – the focus will move to the header even if there are additional items that have scrolled up off of the screen.
- Swipe three fingers to move a page at a time through the list. Once a new page is visible, swipe or slide one finger to traverse through the visible items.
Using these techniques you can get to all of the list items. However, I have noticed some quirks that I think are issues with VoiceOver and/or the interaction with the browser.
Focus sometimes disappears off of the screen. An item that has scrolled “behind” the header or footer will sometimes receive focus and be spoken by VoiceOver. Swiping to the next or previous item usually causes the container to scroll and the next/previous item is now visible on the screen. However, sometimes (this is not always reproducible) after the item has been scrolled into the visible area of the screen, the focus indicator is missing. Moving to the next/previous item one more time restores the visible focus indicator. Since the non-visible item is spoken, losing sight of the item is not an issue for folks who are not looking at the screen. It is confusing for folks who are using VoiceOver for keyboard only support and have the voice turned off. When the focused item is not visible on the screen these users can not see the information! The work around is to move to the next/previous item a few times until the content scrolls and the focus is properly displayed.
The image belows shows the focus ring overlapping the footer:
I also noticed that the height of the items affects the loss of focus and visibility. Items that are taller (the height is a larger value) do not scroll off the screen as often as items that are shorter. Notice the behavior difference with VoiceOver when accessing the following files:
- overflowListSimple.html – the item height is height:42px;
- overflowListSimple32.html – the item height is height:32px;
- overflowListSimple22.html – the item height is height:22px;
In my testing on my iPhone 4S with iOS 6.1.3 the focus problems are more prevalent when the item height is smaller. I am anxious to test this with iOS 7 and see if things work better!