When JAWS won't read form labels on IE
23.09.2016TL;DR: Try removing role="form"
.
It took me 4 days to find out the above solution and, what makes me even less proud, I didn’t even do it myself! In the following article, I’d like to share the hard parts of fixing accessibility bugs.
The bug
I was given a defect, which could be generalized like this:
When moving through form fields with TAB key, at certain field JAWS starts reading from the top instead reading just the field’s label. This happens only on IE.
All the steps
At the beginning, it smelled like a trivial missing label (remember that they’re paired with fields by equal values of for
/id
attributes of respective tag). Imagine how shocked I was when JAWS List of Form Fields tool (INSERT+F5) showed all the fields perfectly labelled and even correctly read every single label on highlight. Still, after activating the problematic field, JAWS failed to announce it properly.
I also tried to “strengthen” the labelling by adding aria-label
and aria-labelledby
attributes here and there, but without success. Later I scanned the page again with AccChecker, just to confirm there was no problem with field/label pairing.
Then I blamed Angular.
The form lived in an application with routing, data binding and all the fine ng-goodies. The form made use of some custom directives, and it was easy to assume that maybe some JavaScript is messing with focus, tabbing order or keyboard events. I stripped all unnecessary attributes from the code, but unfortunately the buggy behavior was still there.
The next thing to check was structure of the whole page. The idea behind this was reasonable: if there was some unclosed tag, the focus could “leak”. Quick validation resulted in no markup errors.
At this point I was pretty frustrated. I really wanted to know what’s wrong with the JAWS + IE, but ran out of ideas. Out of suspicion, I put together this basic, clean form:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test form</title>
</head>
<body>
<form role="form" name="form" id="form" novalidate method="post" action="jaws-form.html">
<h2>Test form</h2>
<div>
<label for="amount">I want to borrow</label>
<input id="amount" name="amount" type="number">
</div>
<div>
<label for="years">Over a term of years</label>
<select id="years" name="years">
<option value="a">Option a</option>
<option value="b">Option b</option>
<option value="c">Option c</option>
</select>
</div>
<div>
<label for="months">Over a term of months</label>
<select id="months" name="months">
<option value="x">Option x</option>
<option value="y">Option y</option>
<option value="z">Option z</option>
</select>
</div>
<div>
<label for="purpose">What is the purpose of this loan?</label>
<select id="purpose" name="purpose">
<option value="fickcar">Fick car</option>
<option value="buckcar">Buck car</option>
</select>
</div>
<div>
<label for="day">What day of the month should we take your loan repayment?</label>
<select id="day" name="day">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
</body>
</html>
Looks innocent, right? Sadly, when TAB-bed to the last field JAWS fails to read its label and instead starts reading from the top!
What’s even weirder, this behavior can be fixed by applying random changes like:
- changing options’ text content;
- moving
h2
element out of form; - (my favorite) removing question mark from last field’s label.
WTF? I’d like the control over my form, please. I don’t want to shuffle the content and structure until I find single combination that satisfies the screen reader!
Then my colleague wrote to me:
What if you removed that role=”form”?
The very last thing I haven’t tried. Because I believed it was necessary. Because Bootstrap used to use this markup in their docs.
And boom. It started working. On IE. With the original form. Regardless all the ng-additions.
What I know now
- Collaboration and having an extra pair of eyes is really helpful
when dealing with weird bugsevery day. - JAWS has no debugger or “inspector” tool, therefore I still can’t say for sure why this fix worked!
role="form"
is considered redundant for the form element.- There aren’t many knowledge sources about JAWS and accessibility on the internet, compared to purely visual front-end web development areas. It may be an interesting niche to expert at.
Links
- https://www.w3.org/TR/wai-aria/roles#form - a W3C specification for role form
- http://stackoverflow.com/questions/21922305/how-does-role-form-help-accessibility - SO topic explaining
role="form"
as a webpage region and implicitform
semantics - https://github.com/twbs/bootstrap/pull/15125 - Twitter Bootstrap PR removing
role="form"
from code examples - http://acccheck.codeplex.com - UI Accessibility Checker, a Windows application for verifying a11y in desktop programs and the web