How to do accessible inline errors for form selects? - html

We need to update our forms to be accessibility compliant. I am looking for information on how to write an inline error for a form select. I have the form field labeled and have an inline error, but the readers do not announce the error.
Here is what we are using
<div class="select-wrapper">
<label for="securityQuestion" class="control-label bolded">Security Question</label>
<select id="securityQuestion" name="securityQuestion" class="form-control" aria-describedby="securityQuestion_error">
<option value="0">Select a Question</option>
<option value="10">What is your mother's maiden name?</option>
<option value="9">What's your town of birth?</option>
<option value="11">What is your father's middle name?</option>
<option value="12">What street did you live on when you were 10 years old?</option>
</select>
<div class="clear form-error-msg" id="securityQuestion_error"><span class="shop-icon icon" aria-label="Attention">r</span><span id="error-msg-text">Please select a security hint question.</span></div>
</div>
So if the user doesn't select an option and submits we dynamically inject an error just after the form field as shown above. This works fine for inputs and text boxes, but for the select, the reader skips it.
I been reading different blogs and specs and have read many times, don't use selects, but use radios or text boxes instead.
So any ideas?

Your issue might be linked to the following bug:
JAWS does not announce aria-describedby on select box in IE
This is also described on WebAim mailing list.
This is a bug, you have multiple alternatives to avoid this bug :
including the error text in the label
ARIA21: Using Aria-Invalid to Indicate An Error Field
SCR18: Providing client-side validation and alert
Re-displaying a form with a summary of errors
Providing error notification as the user enters information
Including error notification information in the page title
For instance, you can use aria-labelledby to target both the label and the error text.
<div class="select-wrapper">
<div id="securityQuestion_label">Security Question</div>
<select id="securityQuestion" name="securityQuestion"
aria-labelledby="securityQuestion_label securityQuestion_error">
<option value="0">Select a Question</option>
<option value="10">What is your mother's maiden name?</option>
<option value="9">What's your town of birth?</option>
<option value="11">What is your father's middle name?</option>
<option value="12">What street did you live on when you were 10 years old?</option>
</select>
<div class="clear form-error-msg" id="securityQuestion_error">Error message</span></div>
</div>

Well, get got our answer. Selects are not consistently supported across screen readers/os/browser combinations. The code works correctly with Safari and voiceover. However, chrome and voice-over do not play nice 100%. Further testing, sadly using chrome vox with chrome doesn't even read text input inline errors.
After some research, we found this from WebAim :
Firefox works best with NVDA
Chrome & Internet Explorer with JAWS on Windows
Safari with VoiceOver
Edge with Narrator

Related

Autofill Broken for Credit Card Expiration Date

For a credit card expiration date, which form elements are “correct” and play nicely with browser autofill?
I’ve seen two main ways of doing it. As a Safari user, this is the most common field that silently fails when I’m auto-filling payment information. Here’s a failure from a real-life experience:
<select>-based field
<label for="billing-cc-exp" class="inputLabelPayment">Expiration Date:</label>
<select name="billing-cc-exp" id="billing-cc-exp" onfocus="methodSelect('pmt-gps')" autocomplete="off">
<option value="0322" selected="selected">03/2022</option>
<option value="0422">04/2022</option>
<option value="0522">05/2022</option>
<option value="0622">06/2022</option>
…
</select>
<input>-based field
<label for="frmCCExp">Expiry</label>
<input name="cc-exp" id="frmCCExp" required placeholder="MM-YYYY" autocomplete="cc-exp">
<input> is more frequently recommended (StackOverflow and tutorial examples), but I’m not sure if <select> StackOverflow example) is specifically a problem, or if it’s just more frequently implemented wrong. So what about the above <select> example breaks autofill, and how would you fix it?
Update: autocomplete isn't the problem
I’ve tested autocomplete="cc-exp”, and the form is still broken for Safari AutoFill, so my self-answer answer is wrong (or at least insufficient).
<select name="billing-cc-exp" id="billing-cc-exp" onfocus="methodSelect('pmt-gps')" autocomplete="cc-exp">
<option value="0322" selected="selected">03/2022</option>
<option value="0422">04/2022</option>
…
</select>
Look at the HTML autocomplete attribute on each of those form fields!
The form elements are not the problem here.
Your broken example has autocomplete=off, as dumb as that is for an expiration date field. The (presumably) working examples have some combination of autocomplete=cc-exp or cc-exp-month and cc-exp-year.
Fixed webform:
<label for="billing-cc-exp" class="inputLabelPayment">Expiration Date:</label>
<select name="billing-cc-exp" id="billing-cc-exp" onfocus="methodSelect('pmt-gps')" autocomplete="cc-exp">
<option value="03/2022" selected="selected">03/2022</option>
<option value="04/2022">04/2022</option>
<option value="05/2022">05/2022</option>
<option value="06/2022">06/2022</option>
…
</select>
There's nothing special about Safari going on here. Chrome looks to the same attribute (related post). Autofill can work without the attribute, as in this JSFiddle example, but autocomplete=off will break it!

Chrome 77 caching <select> selected option, even with autocomplete="off"

If a <select> element has a selected option, Chrome will ignore that selected option even if autocomplete="off" on the <select> element when using the browser's "navigate back" functionality. One workaround I have found is wrapping the select in a <form>, but I don't want extraneous forms in my html.
Question: Is there a way to fix this in Chrome without wrapping in a form element? (This behavior does not occur in Firefox, haven't tested other browsers)
To reproduce, using Chrome 77:
1.) Visit this jsfiddle, and change both selects to "One". Note that "Two" is the selected option for both, so when the page loads this is what should be selected in both elements
2.) Click on the link to google (page navigation won't actually occur, jsfiddle output can't actually navigate to webpages)
3.) With your mouse having clicked in jsfiddle output, click the browser's back button
4.) You'll note that the select element which is wrapped in a form has the correct element selected by default, "Two". The select element which is not wrapped in a form has the incorrect element selected, "One"
https://jsfiddle.net/m5hg8n40/1/
<!-- chrome ignores 'selected' -->
<select autocomplete="off">
<option value="1">One</option>
<option value="2" selected>Two</option>
</select>
<br><br>
google.com
<br><br>
<!-- chrome obeys 'selected' -->
<form autocomplete="off">
<select>
<option value="1">One</option>
<option value="2" selected>Two</option>
</select>
</form>
MAC OS Catalina 10.15
 Browsers
Google Chrome Version 77.0.3865.120 (Official Build) (64-bit)
Safari Version 13.0.2 (15608.2.30.1.1)
Firefox 70.0
 Actions tested:
Onload the jsfiddle i see both with the two option selected
If i click google link and go back, both keeps two selected
If i modify first select (without form) to one, go google and go
back, it keeps the one selected
If i modify the second select (with form) to one, go google, and go
back, it will show the two option selected
So as far as i see.
On load works for both, but the window History treats slightly different both input select, if they are wrapped or not in a <form>tag
One will keep the last action executed, and the other will take priority of the form to reset its inputs to the default state.
Excepcion: Firefox treat both with the same behavior (like without the form)
For me it seems legit to use the tag there if you need it, they can be use to collect data even if they are going to be used locally or remotely.
( is not worse than pages having 1047248 <div>'s everywhere and zero semantic HTML ) so its really up to you i think. And if you need to store data in another way you could use LocalStorage
I think you can't do anything without js.
<body onload="document.querySelector('select').value = document.querySelector('select [selected]').value">
<select>
<option value="1">One</option>
<option value="2" selected>Two</option>
</select>
<br><br>
google.com
<br><br>
<form autocomplete="off">
<select>
<option value="1">One</option>
<option value="2" selected>Two</option>
</select>
</form>
</body>

Blue highlight persisting on option text in select input after clicking away

I have a simple form with some select options that need to do stuff when the options are changed (create new form elements). This all works fine, however when a select option is chosen and the user clicks elsewhere on the page (either another form option or a blank area of the page) the text of the chosen option remains highlighted blue.
I've used select's before and not had this problem, however they weren't linked to the .change function. Is that something to do with why this is happening? Has anybody encountered this issue before? All help greaty appreciated! Code is below...
<div id="container1" class="form-group">
<label class="control-label">Select an option</label>
<div>
<select class="form-control" id="mySelect">
<optgroup label="A">
<option value="1A">Option1A</option>
<option value="2A">Option2A</option>
<option value="3A">Option3A</option>
<option value="4A">Option4A</option>
</optgroup>
<optgroup label="B">
<option value="1B">Option1B</option>
<option value="2B">Option2B</option>
<option value="3B">Option3B</option>
<option value="4B">Option4B</option>
</optgroup>
</select>
</div>
</div>
I've seen the issue brought up here
Remove Blue highlighting of option
However I don't think this quite describes my problem, as it seems to me that that person wants to remove the blue highlighting whilst using the form (hard to be 100% sure though). I don't mind the blue highlighting being there when using the form, I just want it to stop persisting when you stop using the form and do something else on the page.
UPDATE: Problem only seems to occur in Internet Explorer (tested versions 9, 10 and 11). Tested in Chrome and issue doesn't occur. Just to elaborate on the comments, the issue has nothing to do with JS (so I have removed the JQuery code and subsequent tags). The issue occurs when using optgroups in a select form. Loading the HTML outlined above into IE produces the error.

get jaws to read all options in a select

Is there a simple way to get jaws to read all the options for a select, currently we have
<div class="mySelectLabel">
<label for="mySelectId" class="mySelectLabel">
<span class="required" aria-hidden="true" role="presentation">*</span>
<span class="offScreenText">Mandatory</span>
<span class="labelText">Are you old enough?</span>
</label>
</div>
<div class="myDivClass">
<select id="mySelectId" name="mySelectName">
<option value="">Please Select...</option>
<option selected="selected" value="Y">Yes</option>
<option value="N">No</option>
</select>
</div>
Currently jaws reads ... Are you old enough? Combo box Yes the client wants it to read all the options.
I figure I could output hidden text for jaws to read but it would be nicer if there was an aria setting or something similar I could apply.
This is one of basic navigation rules with JAWS.
Actually JAWS should read:
Are you old enough? Combo box Yes
If a user hears that this is a combo box, he/she knows (at least, should know) that in order to navigate he/she must press the Enter key in order to turn on the forms mode (unless the automatic forms mode is turned on). When in forms mode, he/she reviews the combo box with his/her vertical arrow keys.
This is intended behavior, again, navigation with JAWS works like this.
What you can do if you are absolutely required to do such a thing is the following: put an aria-describedby attribute to your select and in the description (which is visually hidden, of course) put something like this: «Select from one of the following values: Yes, No» (sure, you can grab the values from the options array with some JavaScript).

select vs multiple with required attribute behaves inconsistently

I have a basic form like so:
<form id="test-form">
<select id="multi" name="mymulti" multiple required>
<option value="">Choose a different Option</option>
<option>Foo</option>
<option>Bar</option>
<option>Baz</option>
</select><br>
<select id="single" name="myselect" required>
<option value="">Choose a different Option</option>
<option>Foo</option>
<option>Bar</option>
<option>Baz</option>
</select> <br>
<input type="submit">
</form>
The key point here is two selects, both required, but one is multiple and the other is not.
If you choose the default options (note you actually have to click on them), and then submit the form, it will tell you that the single select is required, but not the multiple select.
I looked at the relevant portion of the html5 spec, and although there is some talk about how the required select interacts with placeholder elements, I don't see anything about how multiple+required behaves.
The above behaviour is only in Chrome, other browsers seem to behave the same for both types. My question is, why? It seems... inconsistent. I understand how to work around it with some javascript, just not why I would have to? Can anyone explain the rationale behind this?
Demo (remember to actually choose the placeholder options).
Chrome is acting right here. While implementation in FF is simply simpel. But chrome's implementation does not only follow the spec, it is also simply logic. If a mutliple or size > 1 select is used, there is no placeholder by definition. And without a selected attribute there is indeed nothing :checked (i.e.: selected) initially.
In case of a single select with size=1. The select > option:first-child with an empty value is the placeholder option. And a single select has always one option :checked/selected.
Here is a definition of placeholder option in JS: https://github.com/aFarkas/webshim/blob/gh-pages/src/shims/form-shim-extend.js#L88-94 and here a definition of valueMissing for select: https://github.com/aFarkas/webshim/blob/gh-pages/src/shims/form-shim-extend.js#L128-130