Transcript: Todd Kloots — “Developing Accessible Widgets with ARIA”

Transcript:

Todd Kloots: Thanks for coming everybody, if you don’t know me already my name is Todd Kloots, I’m a member of the YUI team. And today I’m going to be talking about developing accessible widgets using the ARIA specification. And the agenda for today’s talk will be to introduce ARIA, of course, and also just provide some practical tips for configuring your environment when you’re a developer working with ARIA, because that’s one of the most important things that I felt was a difficult thing to learn, when starting out, and I am hoping that I can pass that knowledge on to you guys. Also, how to use ARIA to improve the accessibility of existing DHTML widgets that you may have.

So, why the need for ARIA? I think that ARIA’s important because in today’s environment where we have so many rich DHTML widgets available to users — you know, we’ve styled them to look exactly like desktop controls in many cases, we’ve added all of the necessary keyboard enhancements hopefully, and for all practical purposes they looks and feel exactly like a widget on the desktop. But there is, unfortunately for users of screen readers, a perception and interactivity gap in a lot of those cases. And I want to demonstrate that perception and interactivity gap through the use of a quick example.

So this example is one of the YUI menu examples, and I’ve taken a quick screen cast of what that experience is like in a menu without ARIA enabled. So I’ll just play that video quickly for you now.

[Video plays]

So in this video, you know, the way I developed the YUI menu control, I developed it with semantic markup — all the menu items are analysed, so it’s a list-based structure, I added all the keyboard controls, it’s obviously styled to look like a desktop menu. But in this video, I have the NVDA screen reader running, using Firefox — as you can see, although it looks like a menu and it performs like a menu, the screen reader still interprets that to the user as a set of lists. And although that’s pretty good, we can do better. And so, in this next example, here is the same exact menu code but added in are the ARIA roles and states, and here’s a quick example of how that experience is now improved.

[Video plays]

So the key difference here is, one: these things are not announced as HTML elements anymore, but rather they’re announced as the widget controls that we’re styling them and creating them to be, with scripts, events etc. Also, as you might remember from the previous movie, when you would move over the root items of the menu bar, although it said it was a link you would have no idea there was actually a submenu there, whereas now that submenu is announced. And also the items are no longer announced as links but as menu items. So the overall semantics of this widget are now properly conveyed to the user as well as the interactivity of it is now more familiar for users of screen readers.

So, working with ARIA, what do you need to do to get started? So you’re going to need some software to get up and running and developing with ARIA, and I find that there are three main things that you’re going to need to do that. The first is some virtualization software — whether you’re working on Mac or Windows, I find that the first thing you should really do is install some sort of virtual machine, either Parallels, VMWare Fusion, or Virtual PC, and the reason for that is that a lot of times when you’re installing a screen reader is that something could go wrong, you could have some pickups during the install process that could screw up your system, or, you know, who knows, something could go wrong, especially to sandbox the environment.

The next thing you’re also going to need is a browser that supports ARIA, that is supported by a screen reader that also supports ARIA. So ARIA really requires a team effort between a browser and a screen reader. Not every screen reader is designed to work with every browser, and not every browser supports ARIA, so you really need something that supports both. Currently the browsers that support ARIA are IE 8 and Firefox 3, Safari 4 which is coming soon will also supply ARIA support, Opera currently also supports ARIA but unfortunately Opera falls into one of those categories of browsers that are not supported by screen readers. So again, the key take away here is that it’s a team effort between the browser and the screen reader.

The other thing I wanted to mention, you know, is screen readers are often very expensive pieces of software into the thousands of dollars. And so the good thing about them is — the two major screen readers, Jaws and Window Eyes, provide free trials, fully functional versions of the software that you can download from the manufacturer’s website. Now those do come with the catch that these software, these free trials only work for 30 minutes or 40 minutes and then the required system restarts, so virtualization software can greatly help with that, so you can set up your application environment for testing, take a snapshot of that and then reverse that snapshot repeatedly for your testing without having to completely restart your system. It gives you some efficiency on top of the benefit of sandboxing. There are also two free screen readers — there’s NVDA, which is available for Windows, and currently only works with Firefox. But I find it actually has the best ARIA support, better than Jaws and Window Eyes, and so that’s great for developers. And there was the Orchestrator for Linux. And I found also on Windows screen readers only support, again, Firefox and IE, so just as a heads up for what the current environment is, in terms for screen readers and browser support.

So, just a quick checklist again of the required softwares — you going to want to get some sort of virtualization software, you’re going to want to download all the screen readers that currently support ARIA. And also you’re going to want to make sure that the browsers you’re working with also, or the browser versions, that have ARIA support.

So the next step is installing and configuring your screen reader. There’s a couple of gotchas here that are I think are important to note. I would recommend that, you know, first install the VM and secondly install all the browsers that you’re going to want to be testing, and that have ARIA support — and then take a snapshot of that state. That way, again, if anything goes wrong when you start installing your screen readers, you can always refer back and save yourself a little bit of time.

So once you’ve got that snapshot ready to go, then start installing your screen readers. Now one thing to keep in mind is, obviously, screen readers are designed for people with visual impairments so as a sight reader there’s lots of features and that I find get in my way, or are just not helpful to me — and so I would recommend going into all the preferences settings of your screen readers, and disabling those things that you find are not helpful to you, or, you know, costs you productivity time. And then save those preferences, and then restart your virtual machine, and then take another snapshot — and that way, every time you reverse that snapshot, everything is configured exactly as you would like it, and you can be as productive as possible.

Just a quick example of some of the unwanted features you might want to disable is, you know, most screen readers are designed to automatically start up on system start up, so if you’ve got all these screen readers installed they’re all going to start up right away, and you’re only going to be wanting to test one at a time, so that’s one of the preferences I turn off immediately. The other preference that I usually change is the preference for the keyword shortcuts that toggle the virtual buffer. And if you’re not familiar with what the virtual buffer is, it’s a concept that most screen readers have adopted where once the page has loaded, a snapshot in time is taken immediately of the page’s DOM, and then a bunch of keyboard shortcuts are mapped to that state, allowing you to quickly navigate through the DOM of a page — for example all the headings of a page can be skipped through by pressing the H key. This is a great feature, unfortunately every screen reader has a different keyboard combination for toggling that virtual buffer on and off, and this gets even trickier on a Mac using Parallel’s VMWare Fusion because a lot of the keyboard shortcuts by default average the insert key, so it might be like ‘Insert Z’ or ‘Insert M’ and depending on the map keyboard triggering that insert key, it might require pulling down function of various keyboard combinations, so the lesson I’ve learned is to go in and make that keyboard configuration something a little more generic, and hopefully something that’s more consistent so you don’t have to remember ‘Oh, in Jaws I have to remember ‘Control Shift A’ or in Window Eye I have to hold down ‘Control M’ — whatever the case may be, it allows you, again, to be a little more productive. So those are some of the configurations that I have set up for some of my screen readers that I thought might be helpful.

Again, just a quick summary of what you’ll want to do when you’re setting up your environment — so, get all your software installed, take a snapshot, get all your screen readers installed, configure them, take another snapshot.

So, another thing you can do that is, if you have any problems with doing this inflation, there’s a lot of help internally at Yahoo! and outside the company — internally we have this resource Invictor Star in the accessibility lab, Invictor’s always wonderful at being available to help developers de-bug and help even install, you know, get your environment set up. There’s also the free ARIA community Google group, which is great for throwing questions out to the accessibility community and getting answers. And then there’s also the CodeTalks Wiki which was started by Aaron Leventhal, which is a tremendous resource for ARIA, getting started with screen readers, developing with ARIA. So there are a lot of resources at your disposal — don’t be afraid to use them.

So with that, we’ll now move into working with the ARIA roles, states and properties. So the ARIA specification actually outlines six different types of roles. The first is Taxonomy Roles, which I think of as really just generic interfaces such as widget structure composite — these things are not concrete implementations, but they’re just a way of categorizing other roles, and providing the interface for those.

Then you have User Input Controls and User Interface Elements, and these are actually controls, these are ARIA roles with concrete implementations such as textboxes, menus, etc.

Then you have two other types that define structure — Landmark Roles and Document Structure Roles. Landmark Roles are actually — the history of those are, they are from the implementation spec, and they allow you to specify roles that increase the semantics of sections of a document, so essentially allowing you to identify a whole section of a document as navigation, or the main content section, or secondary content section.

The final type of role are Specialized Regions, and I actually come to think of these as structural roles but for applications, so there’s a role of application, there’s a role of dialogue — these things that are self-contained regions of an application that you can use to let the screen reader know about.

So, I think really practically these six role types break into two different categories — those roles that define structure and those roles that define widgets. Some quick examples of that if you use Yahoo! homepage, we could use a lot of the Landmark Roles, for example, to easily improve the semantics of this page. Generally, you know, we as web developers would start by splicing this page up into sections using bits, and we could increase the semantics of this page just by adding some roles to that bits to really tell the screen reader what the content of this page is. For example, the banner — could stand for the banner role, the main content section of the home page could have the role of main, secondary content pieces could be given the role of complementary, just to show they’re complementary to the main content section, the navigation on the left hand side could stand for navigation.

And then when it comes to web application development, other roles are more appropriate. So this is a screen capture of Yahoo! Mail, and we could start overlaying roles on top of those. One thing to do immediately since, you know, Yahoo! Mail is an all-encompassing application when it’s running in the browser frame, would be to stamp the root-most element with application, let the user know this is not a webpage but this is an application. The tab list inside we could stamp with tab list; the tool bar running inside each tab, obviously, would have a role of tool bar; the tree view running in the left hand side could be an ARIA tree; and then we could use the role of document to let the user know that the email documents themselves are actually documents, they’re not part of the application, they’re content. So, just a quick overview of how the roles can be used.

There are also states and properties that can be levered from the application and those can break into obviously different types — widget states which are straightforward and probably very familiar, something like a widget checkbox being checked. Live Regions, which allow you to designate a certain section of the page as its content being dynamically updating through some means. That’s one thing that screen readers have historically had a problem with — because of this virtual buffers, they get a snapshot of the page in time, any updates to the content of the page that are made through XHTML requests, or changes to the DOM through user requests, the screen reader usually does not get notified of those changes, so Live Regions helps solve that problem by telling the screen reader ‘hey, a section of this page is going to change’.

There are also roles and states that facilitate the screen reader knowing about Drag and Drop interactions. There’s also a category that helps to find relationships between widgets and sections of the page, that further help cement parent-child relationships.

And lastly there are global User Interface Properties — things that just apply to any elements, be they structural, or widgets, something like a property of hidden, so ‘is this content hidden, is this widget hidden?’

And I think that these also can be broken into three different categories — there are states and properties that are directly applicable to that widget, and then there are those that are inherited, and then there are those that are global. And when you looks at specific role designation in the specification, it’ll tell you where those different states and properties come from. So it’ll tell you which different things are inherited into the widget and which things are direct members.

It’s also important to keep in mind that there are two types of states and properties, when you’re working with them in widget development. There are those that are managed states — so these are states that are managed for you by the browser by default, and these are not new to ARIA. So something like the focus states that you’re familiar with, you know, unformed controls. When you tab into a control it receives a focus outline, you didn’t have to add any additional scripting to make that happen; it’s managed for you by the browser, and there are CSS pseudo-classes that map to those states you can take advantage of. These, again, are not new but are these are things that ARIA works on top of.

What is new with ARIA is you have these new states, such as hidden, where it’s actually up to the developer to actually manage the application of that property, and the removal of that property. And that needs to be done through a script. So that’s the designation, that’s what’s new with ARIA, is that you as a developer are required to manage these states.

So, how to add these roles and states to elements in HTML? For roles, it’s just through the role attribute, and you can add them inline as illustrated above. You can add roles and properties through script , through the "setAttribute" method. And all states and properties require the ARIA prefix — so in this case, I am setting something into hidden, so I say ARIA dash hidden, and I set a value of false.

So here are some tips that I’ve found are helpful for working with the roles, states and properties. The first is I think you should always consider use of ARIA as a Progressive Enhancement. And the reason I think that it’s important is that, especially in widget development, where you want to be adding keyboard controls, if you have given something the designation of menu, for example, and you haven’t implemented the appropriate keyboard controls for a widget, and a user of a screen reader tabs into that control, the expectation is you’ve told the screen reader that this is actually a menu widget, as they would normally be familiar with on a desktop, and so you need to fulfil that promise by adding those keyboard controls which require Javascript, and so if support for keyboard is required for ARIA, and in order to implement keyboard functionality we need Javascript, then it makes the most sense to me just to add those roles and states through script.

It’s also important to keep in mind that ARIA is only supported by a subset of browsers and because, in my experience, it’s also required a good amount of testing and tweaks, I typically wrap any of my ARIA code in browser detection so that I can explicitly control which browsers I’m delivering ARIA roles and states to. That way, I’ve tested the experience, I know it works, I’ve gone and run through all the various parameters — that way I’m not just delivering code that I’m, you know, hoping on faith works. So, again, since a good amount of testing is involved then I think it’s important to use browser detection when working with the ARIA roles and states.

So, I think it’s important to use ARIA when it makes sense — not to use it just for the sake of using it. And you also want to avoid roles that, first of all, are abstract roles — things that are, like, window and things that lack concrete implementation — so be mindful of those when you’re reading the spec. Also, I think it’s important to avoid roles that duplicate existing HTML elements. There’s a couple of, there’s about a handful of roles, such as "list", "list item", "img:, and "heading", that are in the spec to make it easier for people who were building pages out of markup that was perhaps not semantic, that was perhaps littered with tables, and people wanted to designate a TV as a heading, etc. It’s my belief that if you’re going to be going in to add roles to nonsensical markups to make it more accessible to screen readers, you might as well just go back in and change the markups to make it be the right markup, before continuing using the wrong markup and have ARIA do that job for you.

The other thing is a lot of times support for ARIA roles is just not there — they’re in the spec but they haven’t been implemented by screen readers or browser manufacturers. And so in those cases — before using a role, I first of all reference the ARIA test cases, they’re available on CodeTalks, where they’ll outline all the various roles, showing you which browsers and screen readers have implemented those roles. Also it’s important to test for yourself because those test cases might be out of date as new screen readers or browsers become available. And when you find yourself in such situations where you want to use an ARIA role and there is no support for it, I always think it’s important to provide feedback to browser manufacturers, screen reader manufacturers, so that people know that the developer community really needs this functionality. But there are techniques that you can use in the meantime to work around that — so, I have one such example of that. So the dialogue role is obviously a very useful role when you’re developing dialogue, and it’s currently not well supported by screen readers, I think only NVDA currently supports it, so, here’s a quick movie of the YUI dialogue using the dialogue role, here’s what, you know, it should sound like in all screen readers.

[Video plays]

So the dialogue becomes visible when the first form field becomes focused, the dialogue’s label is read, personal information dialogue, and its first label for the form filler is read, letting the user know that this is a dialogue and also letting them know the context, position, that they’re in — so that they’re in the first form field. Unfortunately, again, this does not work in Jaws or Window Eyes, two of the major screen readers, so what do you do in those situations? In this particular case I just fell back on what you might call an old school technique, which is I hid some additional text in the label field of the first form field, so that when that first form field becomes visible since the screen reader will read that label, it would also read that hidden text. And that hidden text just essentially says that this is a dialogue, and so here is that example running in a screen reader. Oh, I’m sorry, this is a video of the problem, rather. This is the dialogue role in Jaws not working.

[Video plays]

And then finally, here is my workaround running in Jaws.

[Video plays]

So all I did was, again, added some hidden text, added some additional text rather, via the emphasis tag that label, hid that label off-screen using CSS.

So what are some other things you can do to — what are some other tips, rather, for working with ARIA? One of the things you can do is you can use these statement properties that are specifically defined for improving the relationship between elements on a page. Two of the most useful are "labelledby" and "describedby". And "labelledby" essentially allows you to provide a simple label for a UI control; what you do is you set the label to the attribute by the ID of the element that’s labelling this control. So it works very much like the label attribute for all elements. It has a sibling, "describedby", which allows you to provide some additional, supplemental description for the widget.

There’s also "owns" and "controls" which are really great, but are not implemented currently. "Owns" essentially allows you to establish a parent-child relationship for elements where the parent-child relationship are actually not communicated through the DOM hierarchy, and I’ll talk a little bit more about that in a second. And "controls" allows you to say this this UI control controls another UI control. Again, it would be wonderful if it worked, but it’s not there yet.

The other useful role I’ve found for working with defining relationships between elements is the use of the role of "presentation". I find that in cases where I want to use "owns" and it doesn’t work, I can use the role of "presentation" to actually collapse elements that are between a parent and child, so that that parent-child relationship is restored, and I’ll have a little demo of that in a quick second. It also is useful for removing default roles that are associated with certain elements, for example if I’m transforming a list into something else, a lot of times screen readers have a default role applied to list items, and if I want to null that out, I can apply the role of "presentation" to that, so that also comes in handy.

So, a quick demo of this relationship building would be the ARIA tab view example. So in this example, following the YUI tab view mark up, I place the role of "tablist" on the "ul" that finds the set of tabs, and I define the role of tab on each anchor element inside the "li". Unfortunately for all the screen readers that caused the problem — what should happen when you focus into the first tab, it should tell you which tab you’ve focused on, and how many tabs there are total.

[Video plays]

When you tap into the control it tells you, you know, ‘you’re in tab 1 of 4′ and that’s what should happen. Unfortunately, again, because of the role of — by default applied the list items — you don’t get that context. And so the solution I’ve found is to apply the role of "presentation" that "li" that is the parent of the tab, and that allows you to restore the parent-child relationship between "tablist" and its children tabs. And that way, when the user tabs into each tab, they get the full context of how many tabs are in the tab view.

Another way you can use ARIA — another tip for using ARIA — there are lots of roles and states that can be used to just improve the basic semantics of any HTML page, they don’t apply to specific widgets. For example we already went through landmark roles. You can also use the ARIA role as hidden to convey the state of any hidden elements on that page. You can also greatly improve the accessibility of any forms with the required, invalid and disabled properties and states. I also find that the role of presentations really useful any time I’m using iframe shims, if I set the role of presentation on the iframe shim then set the tab index on "-1", that way the user can’t tab to, or see, any elements that I’m using purely for presentational purposes like a shim, or if you’re using iframes for some sort of data transport mechanism. And again, Live Regions are great for when you’re using any informational elements.

There are also cases where you can tweak existing HTML after you’ve applied roles and states to further improve the accessibility of that widget with a shimmeter. One example that I found that was really helpful was with menu. Each item in a menu is a list item, and when it’s not a navigational menu item, I just set the "href" attribute of that anchor to "#". Unfortunately, what this resulted in is that screen readers tabbed each item menu — they actually will read the context of that "href". And so what I found is that after I apply the role of "menuitem" to each of those anchors, I then use script to remove the "href" attribute, and that way the screen reader still announces the menu item properly, but doesn’t announce the "href".

Another thing you can do is, once you have applied the roles and states, if there is any CSS specific your page when ARIA is enabled, you can use CSS attributes to apply ARIA specific styles. So in this case if I want to change the focus outline on anchor elements when ARIA’s enabled, I can use the attribute selector to apply that specifically to anchor elements with the role of "menuitem" and then use the CSS focus pseudo-class to do so.

The other thing that’s really helpful from a technique standpoint is, you can use ARIA in a piecemeal fashion. So there are many ways in which web development of widgets is further ahead on the desktop — there are widgets that are very familiar to users on the web that are not so familiar on the desktop and therefore they lack support from ARIA currently. Things like Accordions, Carousels, and then there’s even established widgets on the desktop like Calendars that currently have no ARIA support. So one thing you can do is, you know, start by building those widgets out of current best practices, and then pepper that markup with ARIA, to make it more accessible.

One example of that was when we were working on the YUI Carousel. So currently there is no Carousel role, and so to make Carousel accessible what we did was used several different roles to — that made sense in the context of the Carousel — so first built it based on semantic markup, because it’s based on some list elements. The toolbar of the Carousel is using the "toolbar" role, all the buttons are marked with the "button" role, the "listbox" role is used for the content area of the Carousel, and each section or frame of the Carousel’s content is the "option". I also used the "labelledby" attribute to label both the header and the listbox elements with the same label — so that way when the user is tabbing from the toolbar into the content area, the label is repeated to further cement that these two have the same label, they’re part of the same control. And ideally I should have been able to do that by using the "controls" attribute to say, you know, the toolbar drives the Carousel concept through the "controls" property, but again, since that’s not supported, you do the best that you can do.

So here’s a quick demo of what the Carousel sounds like in the screen reader with ARIA enabled.

[Video plays]

So the key take away here, you know, is just because there isn’t explicit ARIA support for your widget, there are things you can do — you can be inventive, and come up with other solutions.

The last tip I would have is test like crazy. Test using each of the browsers that you support, test using all the various screen readers. Test with your eyes closed. And also, leverage people who have disabilities, since they are going to be using the software much more than you, they are more familiar with it, they have a tremendous amount of insight to offer. I am constantly leveraging Victor Strong, we have him as this wonderful resource, he has insights into the usability of widgets used in the context of screen readers that I never could even think of, so, you know, leverage your resources.

And again just a quick summary of all the tips for working with the ARIA roles.

As I said earlier, one of the things about ARIA is it requires that you implement the correct behaviors for keyboard accessibility, because you’ve said that this thing is a widget on the desktop, and now you need to fulfil that promise by adding the keyboard support, otherwise the user of a screen reader who is completely dependant upon keyboard is going to tab into that control, expect to use the Enter keys, or Escape, etc, and none of that’s there. And so, although you’re saying it’s this kind of widget it’s not behaving like it’s the widget that you told the discriminator that it is, so keyboard access is absolutely essential.

So make sure that there is a keyboard equivalent for every mouse interaction that you have, and again make sure that you fulfil that expectation as completely as you can. So to do so, there are tons of guidance from an implementation standpoint. The ARIA specification outlines a lot of the behaviors that each one should have from the keyboard perspective. There’s also a complementary ARIA Best Practices document that does the same. AOL DHTML Style Guide has a wonderful reference for what keyboard behavior should be for various widgets. I also find myself just studying the desktop — you know, just start up Windows, start up Mac, play with the desktop equivalent of the widget you’re doing because a lot of times what’s best for one OS is not implemented 100% in the same OS, or is implemented differently, so I find that I take a little bit from both — whatever works best for the implementation. Also, ask for help from the developer community.

One other thing that’s really important when you’re developing keyboard controls for your widget is that you should have one tab stop per UI control. So if you have a menu, not every single menu item in the tab menu should be in the tabs by default. And this is important for using the screen readers, because if you’re using the tab key to navigate between major sections of the page, or major widgets in application, you want to be able to do that quickly. And so I should easily be able to tab from, for example, a tab control, to a menu, to a tree view. Once I’m inside the context of that control, then I can use arrow keys, or some other keyboard combination to move between the descendants of that widget. So this allows you to be a lot more productive as the user of a keyboard.

There are two techniques for implementing this kind of functionality: one is called the Roaming Tab index technique, and the other leverages this audio property called "activedescending". So for the Roaming Tax index technique, what you would do is, the first focusable descendant in your widget would have a tabindex of 0, so that’s in the normal tab flow of a document. All other focusable descendants would have a tabindex of -1 by default. Once the user tabs into that control, they’re going to hit the descendant with a tabindex of 0 first, then, as they’re arrowing or moving between active descendants, you’ll be updating that tabindex property to reflect the currently focused item. So the currently focused item always has a tabindex of 0, and the items that are blurred have a tabindex of -1.

The benefits of this technique is you can leverage natively focusable descendants to build your descendants, and this technique will also get you the familiar focus highlight ring that is familiar to the user on the OS, so that the learn-ability of the focus of the control is very easy — it’s in line with what the user is familiar with on a desktop. The disadvantages, of course, are just having to manually manage the focus and set the tabindex attribute, and that sometimes calling focus on an element that is further down the page can result in a page scrolling up to the point where, or scrolling down to the point where that focus element is. So a lot of times you have to prevent the default behavior of the event, in order to stop scrolling. So there are a few gotchas, but in general this technique works very well.

The other technique is, again, using this "activedescendant" property, what this allows you to do is to specify a single tabindex for your widget on the root element, so you get that a tabindex of 0 so it’s in the tab flow, and then the currently activedescendant, the piece the user’s interacting with, has the activedescendant property applied to it. I’m sorry, the activedescendant property takes the ID of the activedescendant in the widget. This saves you from having to manage focus withinin the widget, but it also means that you have to implement kind of a pseudo-focus kind of style on any of those descendants so the user knows where they inside the widget — what menu they’re on, or what item in the tree view, or what tab is selected. So this kind of works a little less with the grain, a little more against the grain in my opinion. There may be some use cases for it — I think that it’s up to every developer to use their best judgement. I generally use the other technique, the Roaming Tab Index technique over this technique, because it works a little more with the grain.

Some quick keyboard access tips — again, I think it makes sense to deviate from the desktop when it makes sense to do so. Obviously desktop tab view behavior, for example, focusing a tab automatically loads the content of that tab and displays it — when it came time for developing the ARIA implementation of the YUI tab view, that model didn’t make a lot of sense, especially since the content of any tab can be loaded asynchronously, and if you were quickly cutting between tabs and didn’t want to fire off a bunch of exational HTP requests — and so I went with the model for the Mac, which is when voice over is enabled in the Mac, you can select a tab without the tab content loading, it’s a click that is actually the specific interaction that loads the tab. And so, again, deviate from desktop patterns when it makes sense to do so.

So it’s important to provide a consistent and reliable rendering of focus. Either match the rendering of focus as provided by the host operating system for the browser, so it’s familiar to the user, or provide something that’s completely consistent within your applications, so that the user only has to learn the focus model once. And when it comes to implementing focus you can leverage the YUI Event Utility’s onFocus and onBlur methods which allow you to listen for focus and blur on a widget at a high level, such as a container, similar to event delegation but it uses capture mode since the focus and blur events don’t bubble, currently, in OpD or Apia browsers.

So quick tips for allowing you to focus — also just try to work with the grain, as much as possible. As I said earlier, I think about the Roaming Tab Index technique as it allows you to leverage natively focusable HTML elements for the descendants of your widgets. It also allows you to provide keyboard access across your widgets, regardless of whether ARIA or Javascript is enabled, so that you can provide more of a Progressive Enhancement experience. So if without Javascript your menus are just a set of lists with anchors for every part of the menu, you can still click those items and navigate off to the page that they’re supposed to take you to without Javascript being enabled. So again, more of a Progressive Enhancement, with the grain, kind of, technique.

So quick summary again. I think using the Roaming Tabs Index technique over the "activedescendant" property is the way to go. I also think that when you’re managing tab index, use the tab index act as a property directly on the elements, the camel case version, as opposed to going through "setAttribute" — the reason being is that in IE, "setAttribute" is case sensitive by default, and this is the most compatible and shortest syntax that you can use. Also deviate from desktop patterns when it makes sense to do so. Render focus reliably and consistently to increase the reliability and learn-ability of the focus model for your widgets as quickly as possible. And work with the grain.

So the last section I want to talk about quickly is Live Regions. And again, Live Regions allow you to designate to the screen reader the section of this page is going to be updated frequently throughout its life cycle. So just a quick demo I created on a list that is using Live Regions — and in this demo I had a very simple timer that introduced new list items to a list so that I could introduce The Beatles. So here’s a quick, very simple demo of how Live Regions works.

[Video plays]

So very simple demo, but something that would not be accessible to a user of a screen reader by default because, again, any updates to the DOM do not get triggered by default when the virtual buffer is enabled. So Live Region allows you to do so. Another more complicated, or sophisticated example of use of Live Regions again came with the YUI tab view — when you’re loading content in a tab asynchronously, if the content isn’t there immediately when the user tabs into the panel of the tab, they’re not going to see any content, so for this example we use Live Regions to let the user know the content of this tab is loading, and also alert them that the content is loaded and it’s OK to proceed forward. So here’s just a quick example of Live Regions with an ARIA widget.

[Video plays]

Quick demo of using Live Regions of the tab view. So what do you need to know about Live Regions? There are a couple of different properties that are important. There’s the "live" property which controls either — is the "live" region on or off, and if so, if it’s on, how aggressive should the screen reader be with how it gives updates to the user. And you can designate updates as being polite, assertive, or rude — rude meaning that the updates from the Live Region will always interrupt the user no matter what they’re doing. There’s the property of "atomic", which can be set to true or false — that allows you to control how the updates, that piece of content are read to the user, if that atomic is set to on, any change you make to that area in a Live Region, means the entire region will be reread; whereas if it’s false only the changed portion will be read. And then "relevant" allows you to designate what things you want to be read to the users — so is it just additions, removals, etc.

There are several ARIA roles that enable Live Regions by default: "alert", "status", and "log". So when you use those roles, it’s equivalent to saying ‘Live is on’. So although some roles carry with them implicit Live Region support, you can use Live Regions with any HTML elements, so that’s important to know. Three screen readers currently offer support for Live Regions: Jaws 10, NVDA, and the Firevox plug-in for Firefox. And one thing that I’ve found working with Live Regions is a lot of times developers leverage integration to update the content of a section of a page because it’s the fastest way to do it, it’s the quickest way to surrender new content — unfortunately I’ve found that Live Regions doesn’t update the content as you would have designated it via the relevant properties, so that’s why I say only additions and removals, because effectively the entire content’s been gutted and replaced with "innerHTML" — the relevancy of the update doesn’t enter the screen reader appropriately. So it’s really only through traditional DOM API such as a pen child, or remove child that Live Regions work wholly as expected, so there’s some work to do on the side of the screen readers and browsers to get this working with techniques that web developers have become accustomed to using for making applications run faster. So, we need to strike a better balance between accessibility and performance. And, that’s it.

  1. December 15th, 2008 at 11:39
    Reply | Quote | #1

    Thanks for doing this!

    Could you please correct this one mistake:
    “there’s NVDA, which is not enabled for Windows”
    should be changed to read the opposite:
    “there’s NVDA, which is available for Windows”

  2. December 15th, 2008 at 15:51
    Reply | Quote | #2

    Aaron,

    Thanks for the correction — I appreciate it.

    -Eric

  3. December 15th, 2008 at 21:34
    Reply | Quote | #3

    Thanks for providing a transcript – it’s easier to capture main points for others. One note: Erin Leventhal != Aaron Leventhal (in the section mentioning codetalks wiki).

  4. December 15th, 2008 at 23:14
    Reply | Quote | #4

    @Scott Plumlee, Thanks — fixed. -Eric

  5. Jennifer Gauvreau
    January 2nd, 2009 at 15:52
    Reply | Quote | #5

    It’s great to have the transcipt for easy reference.

    There’s a minor typo in the sentence:
    “And I found also on Windows screen readers only support, again, Firefox, not IE, so just as a heads up for what the current environment is, in terms for screen readers and browser support.”
    “Firefox, not IE,” should be changed to “Firefox and IE”

  6. January 2nd, 2009 at 18:45
    Reply | Quote | #6

    Thanks, Jennifer; I’ve made the correction.

TOP