Accessible form validation

The problem

Validation errors communicate important information to your users. HTML offers some basic input validation that works with screen readers, but most apps call for something a bit more sophisticated. ARIA live regions allow you to expose dynamic page changes to assistive tech users, either through aria-live or live region roles.

Validation with HTML

The form below uses native HTML validation by adding the required attribute to the field. The screen reader announces the error automatically, without any other effort on our part.

Here's the form generated by the code above. Test this with a screen reader to hear how it announces the validation message.

Try it yourself

If you're on a Mac you can test this with VoiceOver. Press cmd + F5 to turn it on, then try to submit the form without filling out the input. You should hear the screen reader announce the validation error.

Custom form validation

If you're writing your own validation errors you need to make sure that they're accessible to screen readers too. In most cases, adding aria-live="polite" to the markup containing your error message should suffice. This allows the screen reader to finish any ongoing announcements, then read out the error message.

Below is an example of a Rails view using custom form validation, taken from the dev.to codebase. When the user's email is blank, a series of custom validation errors are announced.

A few lines below, another example uses role="alert". Just like aria-live="assertive", this interrupts any current announcements and immediately reads out the error. Because this approach can be disruptive and annoying to users, it should only be used for critical or time-sensitive notifications.

The problem with ARIA live regions is that they only get announced once. This might be perfect for a quick update like "Form submitted", "Account created", or "Email sent". However, if you have a long form with lots of errors, a user might not remember what errors or instructions were previously announced as they navigate from input to input.

To help with this, you can use aria-describedby to remind the user what they need to do on each input. Below is another example from dev.to, this time in plain HTML. Notice that the validation warning message has aria-live="polite", and the id of instructions paragraph is the same as the input's aria-describedby. This way, the screen reader will announce the validation error when the form is submitted, but will also read out the instructions whenever the user focuses the input.