Form Instructions
Meaningful Instructions
It is important that instructions and other helpful information are provided to users to help them successfully complete a form online. Instructions for groups or sections should be programmatically associated with the group.
Although there is a natural way to create a group label with <fieldset>
and <legend>
, there is no natural way to create a
description that is associated with a group. Adding aria-describedby to
either the <fieldset>
or <legend>
element
doesn't work, so we have to get a bit more creative.
Instruction Semantics
Putting regular text in the middle of a form runs the risk that screen reader users will not hear it because if they're tabbing only to focusable elements, they will skip over all non-focusable text, unless that text is programmatically associated with a group label or an input.
You can use aria-describedby
to programmatically associate instructions
to related form elements.
Required *
Depending on the screen reader certain characters may be interpreted differently. Voice Over Utility on MAC OS for example, reads the "*" symbol as "star." However, some screen readers, like NVDA, cannot read the star symbol.
To ensure screen reader users are aware of required fields add the required
attribute to the input field. Make sure to also reinforce the required property
with aria-required="true"
for assistive technology users. If adding
aria-required
attribute to radio or checkbox groups apply the attribute
to the surrounding <fieldset>
Input types:
- text
- search
- url
- tel
- password
- date
- month
- week
- time
- datetime-local
- number
- checkbox
- radio
- file
Elements
<input/>
<select>
<textarea>
<fieldset>
Help Text
Ensure that each input element has only one label. If an input element has help text, make sure the text differs from the label element text.
Group instructions in <legend>
In the form group below, the instruction is placed within the <legend>
to show that everything within the form is required. Screen readers will
read the <legend>
text when users focus on the first element
in the <fieldset>
.
<fieldset>
<legend class="d-flex flex-column">
<span class="h3">Login Information</span>
<span class="help-text"
>All fields with a <span class="text-danger">*</span> are required</span
>
</legend>
<div class="d-flex flex-column">
<label class="form-label" for="username"
>Username <span class="text-danger">*</span></label
>
<span class="help-text mb-2" id="userNameNum"
>An email address is not a valid username</span
>
<input
class="form-control"
id="username"
type="text"
aria-required="true"
aria-describedby="userNameNum"
required />
</div>
<div>
<label class="form-label mt-4" for="password"
>Password <span class="text-danger">*</span>
</label>
<input
class="form-control"
id="password"
type="password"
aria-required="true"
required />
</div>
</fieldset>
Group instructions using aria-describedby
The aria-describedby
attribute is used to associate the instructions
with the first password field in the group below. We could also associate the
instructions with the second password field, because they're both considered
part of a group of password fields, but in this case once is enough.
<fieldset>
<legend class="d-flex flex-column">
<span class="h3">Create Account</span>
<span class="help-text"
>All fields with a <span class="text-danger">*</span> are required</span
>
</legend>
<div>
<label class="form-label" for="username"
>Username<span class="text-danger">*</span></label
>
<input
class="form-control"
id="username"
type="text"
aria-required="true"
required />
</div>
<p class="help-text" id="mustmatch">Password fields must match</p>
<div>
<label class="form-label mt-4" for="password"
>Password<span class="text-danger">*</span></label
>
<input
class="form-control"
id="password"
type="password"
aria-describedby="mustmatch"
aria-required="true"
required />
</div>
<div>
<label class="form-label mt-4" for="password2"
>Re-enter password<span class="text-danger">*</span>
</label>
<input
class="form-control"
id="password2"
type="password"
aria-required="true"
required />
</div>
</fieldset>