How to Write Accessible Forms

How to Write Accessible Forms

This tutorial can be viewed one part at a time or all in one page.

Don't forget the errors!

Inevitably a user will put bad data into a form, and those errors need to be caught and reported to the user. And the user may need some help to fix the error.

Your form data should be validated at the server for sure. If you want to validate in the browser with Javascript, that's fine too. You need to validate at the server for security purposes. If the submitted form has invalid data, then the user should be sent back to the page where errors are listed in a list of links to the fields that contain the errors. As for accessibility, there's nothing wrong with this approach, but when the page re-loads, the focus will be at the top of the page and a blind user will have to go through the page until they get to the errors so they can fix them and re-submit. The only accessibility consideration here is that you should probably add the word "Error" to the page title so a blind user will hear that they're on the same page, but there are errors to be fixed.

For the remainder of the tutorial we will assume client-side Javascript form validation. We'll assume those functions are already written and we don't need to see how they're done. We'll assume the validate() returns an object with a list of errors, and the id values of the form controls to which they refer.

Reporting Errors with Each Form Control

Another "best practice" would be to put each error with each form control.

<form method="POST" action="#" name="theForm" id="theForm">
<div id="errorBox" style="background-color: #FFFFFF; color: #AA0000; border: thin solid #AA0000; width: 50%;padding:1.5em;" tabindex="0">
<li><a href="#fullname">Bad Full name. Letters and spaces only, please.</a></li>
<li><a href="#password1">Bad password</a></li>
<li><a href="#password2">You forgot to re-type your password.</a></li>
<input type="button" value="Okay" id="okayBtn" onclick='document.getElementById("errorBoxOuter").style.display = "none";'>

<div>Fields marked with <span class="red">*</span> are required.</div>
<label for="username">Username: <span class="red">*</span> <span class="invisibleStuff">(Required)</span></label>
<input type="text" name="uname" id="username" value="myusername" required>
<div class="red">Bad Full name. Letters and spaces only, please.</div>
<label for="fullname">Full Name: <span class="red">*</span> <span class="invisibleStuff">(Required)</span></label>
<input type="text" name="fname" id="fullname" value="B0B Sm1th" required>
<div class="red">Bad password</div>
<label for="password1">Password: <span class="red">*</span> <span class="invisibleStuff">(Required)</span></label>
<input type="password" name="password" id="password1" required aria-describedby="passwordReq" value="x">
<div tabindex="0" id="passwordReq">Passwords should be at least 8 characters, contain numbers, upper and lower case letters and a special character. This way it will be hard for you to remember, but easy for a computer to guess.</div>
<div class="red">You forgot to re-type your password.</div>
<label for="password2">Re-type Password: <span class="red">*</span> <span class="invisibleStuff">(Required)</span></label>
<input type="password" name="repassword" id="password2" required aria-describedby="passwordReq" value="">
<legend>What's your gender:</legend>
<input type="radio" name="gender" value="female">
<input type="radio" name="gender" value="male">
<label for="province">Where do you live?:</label>
<select id="province" name="prov">
<option value="false">Select Province</option>
<option value="ab">Alberta:</option>
<option value="bc">British Columbia</option>
<option value="mn">Manitoba</option>
<option value="nfld">Newfoundland</option>
<option value="nb">New Brunswick</option>
<option value="nwt">Northwest Territories</option>
<option value="ns">Nova Scotia</option>
<option value="nv">Nunavit</option>
<option value="on">Ontario</option>
<option value="pei">Prince Edward Island</option>
<option value="qc">Quebec</option>
<option value="sk">Saskatchewan</option>
<option value="yk">Yukon</option>
<label for="comments">Comments:</label>
<textarea id="comments" name="comments"></textarea>
<input type="checkbox" name="agree" checked required> I have read the <a href="accessibleForms/tandc.php">Terms and Conditions</a> and I agree to comply with them. <span class="red">*</span> <span class="invisibleStuff">(Required)</span></label>
<input type="submit" onclick='document.getElementById("errorBox").focus(); return false; ' value="Submit">

See this example in action.