Accessibility
in pattern
libraries
Accessible
Inline Error
Messages
Examples from this
presentation:
http://bit.ly/hinterror
What are inline
error messages?
Let’s look at a simple example:
Age
Error: Must be a valid age value!
Label
Age
Error: Must be a valid age value!
Form control
Age
Error: Must be a valid age value!
Error message
Purpose of error
messages?
They should inform users that
there has been an error.
They should provide users
with help to fill in the field.
Help should be contextual.
When should error
messages appear?
They should only appear after
users fill in field incorrectly.
They should be either
dynamically injected directly
after focus leaves the field or
on form submit.
Appearance
They should be placed in close
proximity to the form field.
They should not use colour
alone to indicate the state.
They should include some
visual indicator, so they work
without the need for colour.
Age
Error: Must be a valid age value!
Visual indicator
Why
“programmatically
associated”?
Screen readers have two
different modes.
These are “read mode” and
“forms mode”.
“Read mode” allows users to
read and navigate the page.
In this mode, users can’t enter
data into a form.
“Forms mode” allows the user
to interact with form
controls.
Keyboard access is restricted
to elements that accept focus.
Elements that can’t receive
focus will not be announced
to ATs.
Let’s look at a simple example:
<label for="email">Email<label>
<input id="email" type="text">
<p>Error message</p> Label
<label for="email">Email<label>
<input id="email" type="text">
<p>Error message</p>
Form control
<label for="email">Email<label>
<input id="email" type="text">
<p>Error message</p>
Error message
This error message will not be
announced by screen readers
while in “forms mode”.
Why?
Because the <p> is not an
element that receives focus.
And, because the element is
not programmatically
associated with the form
control.
Our aims is to make all inline
error messages
programatically associated
with their form controls.
Four methods
Method 1:

Wrapped label
Using this method, the
<label> is wrapped around
everything else.
<label for="error1">
<span>Age</span>
<input id="error1" type="text">
<span>Error: Must be...</span>
</label>
Wrapped label
<label for="error1">
<span>Age</span>
<input id="error1" type="text">
<span>Error: Must be...</span>
</label>
Label content
<label for="error1">
<span>Age</span>
<input id="error1" type="text">
<span>Error: Must be...</span>
</label> Form control
<label for="error1">
<span>Age</span>
<input id="error1" type="text">
<span>Error: Must be...</span>
</label>
Error message
<label for="error1">
<span>Age</span>
<input id="error1" type="text">
<span>Error: Must be...</span>
</label>
Matching for and id
This method is very well
supported.
OSX Voiceover Windows NVDA Windows JAWS
SafariChrome Opera FirefoxChrome Edge FirefoxChrome Edge
PASSPASS PASS PASSPASS PASS PASSPASS PASS
Method 2:
aria-describedby
Sometimes, it’s not possible to
wrap the <label> around
everything else.
aria-describedby can be used
to programmatically
associate the error message
with the form control.
<label for="error2">Phone number</label>
<input id="error2" type="text"

aria-describedby="description1">
<span id="description1">Error: Must be...</span>
Label
<label for="error2">Phone number</label>
<input id="error2" type="text"

aria-describedby="description1">
<span id="description1">Error: Must be...</span>
Form control
<label for="error2">Phone number</label>
<input id="error2" type="text"

aria-describedby="description1">
<span id="description1">Error: Must be...</span>
Error message
<label for="error2">Phone number</label>
<input id="error2" type="text"

aria-describedby="description1">
<span id="description1">Error: Must be...</span>
Matching for and id
<label for="error2">Phone number</label>
<input id="error2" type="text"

aria-describedby="description1">
<span id="description1">Error: Must be...</span>
Matching aria-describedby and id
This method is well
supported.
OSX Voiceover Windows NVDA Windows JAWS
SafariChrome Opera FirefoxChrome Edge FirefoxChrome Edge
PASSPASS PASS PASSPASS PASS PASSPASS FAIL
Method 3:
aria-labelledby
aria-labelledby can be used
to programmatically
associate the error message
with the form control.
Warning: 

Using this method, the aria-
labelledby content will be
announced to ATs but the label
content will not.
This can be resolved by giving
the label an id and adding this
value to the aria-labelledby
attribute.
<label for="error3" id="label1">Address</label>
<input id="error3" type="text"
aria-labelledby="label1 label2">
<span id="label2" role="tooltip">Error:</span>
Label
<label for="error3" id="label1">Address</label>
<input id="error3" type="text"
aria-labelledby="label1 label2">
<span id="label2" role="tooltip">Error:</span>
Form control
<label for="error3" id="label1">Address</label>
<input id="error3" type="text"
aria-labelledby="label1 label2">
<span id="label2" role="tooltip">Error:</span>
Error message
<label for="error3" id="label1">Address</label>
<input id="error3" type="text"
aria-labelledby="label1 label2">
<span id="label2" role="tooltip">Error:</span>
Matching for and id
<label for="error3" id="label1">Address</label>
<input id="error3" type="text"
aria-labelledby="label1 label2">
<span id="label2" role="tooltip">Error:</span>
Matching aria-describedby and id
<label for="error3" id="label1">Address</label>
<input id="error3" type="text"
aria-labelledby="label1 label2">
<span id="label2" role="tooltip">Error:</span>
Matching aria-describedby and id
This method is well
supported.
OSX Voiceover Windows NVDA Windows JAWS
SafariChrome Opera FirefoxChrome Edge FirefoxChrome Edge
PASSPASS PASS PASSPASS PASS PASSPASS PASS
However, I prefer to use aria-
describedby instead of aria-
labelledby.
These error messages are
additional descriptions to the
form control and its label,
rather than being labels
themselves.
Method 4:
aria-errormessage
aria-errormessage was
introduced with ARIA 1.1 in
December 2017.
aria-errormessage can be
used to programmatically
associate the error message
with the form control.
<label for="error4">Mobile number</label>
<input id="error4" type="text"

aria-errormessage="errormessage1">
<span id="errormessage1">Error: Must be...</span>
Label
<label for="error4">Mobile number</label>
<input id="error4" type="text"

aria-errormessage="errormessage1">
<span id="errormessage1">Error: Must be...</span>
Form control
<label for="error4">Mobile number</label>
<input id="error4" type="text"

aria-errormessage="errormessage1">
<span id="errormessage1">Error: Must be...</span>
Error message
<label for="error4">Mobile number</label>
<input id="error4" type="text"

aria-errormessage="errormessage1">
<span id="errormessage1">Error: Must be...</span>
Matching for and id
<label for="error4">Mobile number</label>
<input id="error4" type="text"

aria-errormessage="errormessage1">
<span id="errormessage1">Error: Must be...</span>
Matching aria-errormessage and id
This method currently has no
support.
OSX Voiceover Windows NVDA Windows JAWS
SafariChrome Opera FirefoxChrome Edge FirefoxChrome Edge
FAILFAIL FAIL FAILFAIL FAIL FAILFAIL FAIL
However, it could become a
viable option in the future.
Using aria-invalid
Regardless of the method, the
aria-invalid attribute should
also be used with form
controls.
This attribute helps inform
assistive technologies about
the state of form control.
The value should initially be
set to false when the form
field has no invalid data.
<label for="error3">Mobile number</label>
<input id="error3" type="text"

aria-errormessage="m1" aria-invalid="false">
<span id="m1"></span>
False value
The value can then be
dynamically switched to true
when the form field has
invalid data.
<label for="error3">Mobile number</label>
<input id="error3" type="text"

aria-errormessage="m1" aria-invalid="true">
<span id="m1">Error: Must be...</span>
True value
Using aria-live
The aria-live attribute
informs ATs that dynamic
changes may occur within a
page region.
This can help when injecting
error messages into a page
region.
<span id="m1" aria-live="off"></span>
No error message
<span id="m1" aria-live="off">Error...</span>
Error message
The three possible values are
off, polite and assertive.
aria-live="off"
AT should not announce
updates unless focused on
that region.
aria-live="polite"
AT should announce updates
at the next graceful
opportunity.
aria-live="assertive"
AT should announce updates
immediately.
The assertive value should be
avoided for inline error
messages.
The error message could be
announced over the top of the
next form control label.
The role=alert should also be
avoided.
The role=alert has an
intrinsic aria-live value of
assertive.
The off value is preferred as it
lets users continue with the
form process without
interruptions.
Conclusion
Make sure error messages are
programmatically associated
with their form controls.
And always test any proposed
solutions - with different
assistive technologies and
with real users!
Russ Weakley
Max Design
Site: maxdesign.com.au
Twitter: twitter.com/russmaxdesign
Slideshare: slideshare.net/maxdesign
Linkedin: linkedin.com/in/russweakley

Accessible Inline errors messages