A Practical Example
Setting aside the likes of GMail for the moment, let’s look again at the accordion control that’s built as an example in my upcoming book. A couple of issues back, we modified this example to make it accessible to keyboard users. All we had to do was include a hyperlink in the heading of each section of the accordion so that it would be keyboard-focusable. As we’ll see, making this construct accessible to screen reader users is equally straightforward—it’s doing both at once that’s a little tricky! To refresh your memory, here’s what the HTML code for this page looks like:<ul class="accordion">
<li id="archer">
<h2><a href="#archer">Jonathan Archer</a></h2>
<p>Vessel registry: NX-01</p>
<p>Assumed command: 2151</p>
...
</li>
...
</ul>
If that’s all there were to this page, it would be perfectly accessible to screen readers. We only get into trouble when our JavaScript code hides portions of the page content by dynamically setting a class of "collapsed"
on the list items that make up the accordion. This class hides all but the heading inside the list item:
li.collapsed * {
display: none;
}
li.collapsed h2,
li.collapsed h2 a:link, li.collapsed h2 a:visited {
display: block;
}
The problem here is that using display: none
to hide an element from view also hides the element from screen readers, and screen reader users are unable to read that portion of the page.
Of course, this might not be an issue if revealing the elements by switching off the "collapsed"
property also revealed those elements to screen reader users. Were that the case, screen reader users could use the accordion just as other users do: by “clicking” a header in the accordion to reveal its contents.
As it turns out, however, this is not always the case. Most screen readers work with a static copy of the page’s visible contents—a copy that is infrequently and unpredictably updated (despite early signs from some vendors that this may be changing). And even in screen readers that do refresh their copy of the page contents in response to the user clicking a link, making the user aware that the content has been revealed is problematic at best.
No, your best bet in this case is to hide the contents of the collapsed accordion in such a way that screen reader users are still able to read them. The most useful technique to do this is called offleft positioning, and the CSS code looks like this:
li.collapsed * {
position: absolute;
left: -9999px;
}
li.collapsed h2,
li.collapsed h2 a:link, li.collapsed h2 a:visited {
position: static;
}
In essence, this technique hides elements of the page by positioning them off the left of the page (9999 pixels off the left of the page, to be precise), where they will still be visible to screen readers.
So now screen reader users can read the entire content of the page without any interference from our JavaScript-driven accordion effects! Problem solved, right?
Well, not quite. You see, offleft positioning not only reveals the hidden elements to screen readers—it makes them available to keyboard users as well! In this case, when a keyboard user taps the Tab key to step through the focusable elements in the page, the focus will also step through any hyperlinks in our hidden content. Since these elements are invisible, the keyboard focus will seem to disappear, leading to angry phone calls.
Since there’s no reliable way to hide elements from keyboard users without also hiding them from screen reader users, we need to take a different approach. How about we do something useful when keyboard focus is given to a hidden element … like expanding the relevant section of the accordion!
We can add to every focusable element within the accordion (except, of course, the links in the always-visible headers) a focus
event listener:
var folds = accordion.getElementsByTagName("li");
for (var i = 0; i < folds.length; i++)
{
var foldLinks = folds[i].getElementsByTagName("a");
var foldTitleLink = foldLinks[0];
addEvent(foldTitleLink, "click", Accordion.clickListener);
for (var j = 1; j < foldLinks.length; j++)
{
addEvent(foldLinks[j], "focus", Accordion.focusListener);
}
}
When triggered, that focusListener
function will expand the section of the accordion that contains it:
focusListener: function(event)
{
var element = this;
while (element.parentNode)
{
if (element.parentNode.className == "accordion")
{
Accordion.expand(element);
return;
}
element = element.parentNode;
}
}
And there you have it—an accordion control that is accessible to both keyboard and screen reader users!
More Complex Cases
As you might expect, not all JavaScript enhancements can be adapted to avoid interference with screen readers and keyboard navigation. Sometimes, the best you can do is make it easier for these users to disable the stuff that won’t work for them. In a recent blog post, for example, Jeremy Keith applauds Dan Champion‘s new social book review site, Revish, which offers users the option of disabling the Ajax features of the site that won’t work with screen readers when they sign up for an account. This solution is nice and slick, allows the user to feel in control, and is extremely easy to implement, too!Frequently Asked Questions (FAQs) about JavaScript and Screen Readers
What is the role of JavaScript in enhancing screen reader accessibility?
JavaScript plays a significant role in enhancing screen reader accessibility. It can be used to create dynamic content and interactive web elements that are accessible to screen reader users. For instance, JavaScript can be used to manage focus, announce dynamic changes, and control ARIA roles, properties, and states. However, it’s crucial to ensure that JavaScript doesn’t interfere with the screen reader’s functionality or create accessibility barriers.
How can I use ARIA roles with JavaScript to improve screen reader accessibility?
Accessible Rich Internet Applications (ARIA) roles can be used with JavaScript to improve screen reader accessibility. ARIA roles provide additional information about elements, which can be particularly useful for screen reader users. For example, you can use JavaScript to dynamically change ARIA roles based on user interaction or application state. However, it’s important to use ARIA roles appropriately and avoid using them where native HTML semantics can be used.
How can I use JavaScript to manage focus for screen reader users?
Managing focus is crucial for screen reader users, and JavaScript can be used to control focus effectively. For instance, you can use JavaScript to set focus to a specific element when a page loads or when a user interacts with a particular element. You can also use JavaScript to trap focus within a modal dialog or other interactive components to ensure that screen reader users can navigate them effectively.
How can I use JavaScript to announce dynamic changes to screen reader users?
JavaScript can be used to announce dynamic changes to screen reader users by manipulating ARIA live regions. ARIA live regions allow you to specify areas of a page that are likely to be updated dynamically. When these areas are updated, screen readers will announce the changes. You can use JavaScript to update the content of these live regions and control when and how these updates are announced.
What are some common pitfalls to avoid when using JavaScript with screen readers?
There are several common pitfalls to avoid when using JavaScript with screen readers. One common issue is creating dynamic content that is not accessible to screen reader users. This can be avoided by using ARIA roles and properties to provide additional information about dynamic content. Another common issue is interfering with native keyboard navigation. This can be avoided by using JavaScript to enhance, rather than replace, native keyboard navigation.
How can I test my JavaScript code for screen reader accessibility?
Testing your JavaScript code for screen reader accessibility is crucial. There are several tools and techniques you can use for this. For instance, you can use automated accessibility testing tools to identify common issues. You can also use screen readers to manually test your code. It’s important to test with multiple screen readers, as they can behave differently.
How can I use JavaScript to control ARIA states and properties?
JavaScript can be used to control ARIA states and properties, which can be particularly useful for creating accessible interactive components. For instance, you can use JavaScript to toggle the ‘aria-expanded’ state of a collapsible element, or to update the ‘aria-valuenow’ property of a slider. However, it’s important to ensure that these changes are announced to screen reader users by using appropriate ARIA live regions.
How can I ensure that my JavaScript code doesn’t create accessibility barriers?
Ensuring that your JavaScript code doesn’t create accessibility barriers is crucial. There are several strategies you can use for this. For instance, you can use progressive enhancement techniques to ensure that your content is accessible even when JavaScript is not available. You can also use ARIA roles and properties to provide additional information about interactive components. Additionally, it’s important to test your code with screen readers to identify and fix any potential issues.
How can I use JavaScript to create accessible forms for screen reader users?
JavaScript can be used to create accessible forms for screen reader users. For instance, you can use JavaScript to provide real-time validation feedback in a way that is accessible to screen reader users. You can also use JavaScript to manage focus and announce dynamic changes in form fields. However, it’s important to ensure that your forms are accessible even without JavaScript, by using appropriate HTML semantics and ARIA roles and properties.
How can I use JavaScript to create accessible navigation menus for screen reader users?
JavaScript can be used to create accessible navigation menus for screen reader users. For instance, you can use JavaScript to manage focus within the menu, to toggle the expanded or collapsed state of submenus, and to announce these changes to screen reader users. However, it’s important to ensure that your navigation menus are accessible even without JavaScript, by using appropriate HTML semantics and ARIA roles and properties.
Kevin Yank is an accomplished web developer, speaker, trainer and author of Build Your Own Database Driven Website Using PHP & MySQL and Co-Author of Simply JavaScript and Everything You Know About CSS is Wrong! Kevin loves to share his wealth of knowledge and it didn't stop at books, he's also the course instructor to 3 online courses in web development. Currently Kevin is the Director of Front End Engineering at Culture Amp.