Notes on Implementation
We implement Bootstrap’s Forms, with some tweaks to the visual appearance to add increased focus styling and a red asterisk for required fields. Also, ally.js is used to add an underline to labels when the corresponding input has focus. The documentation for Bootstrap Forms is applicable, along with the Accessibility Notes below.
Instructions and other helpful information are necessary to avoid errors and help users successfully complete an online form.
Custom Form Elements
We do not recommend using the custom Bootstrap form elements (or any custom form element) unless you are very familiar with the ARIA authoring practices.
Form Control Attributes and Validation
Form control attributes, such as an input element’s
type attribute, can be used to restrict the input value to help avoid errors. HTML5 input types can also help by giving hints to the browser about what type of keyboard to display on-screen. However, because there are so many usability and accessibility problems when using
<input type="number">, we recommend using
<input type="text" inputmode="numeric" pattern="[0-9]*"> instead.
Gov.uk has a good article on this if you’d like to read more: Why the GOV.UK Design System team changed the input type for numbers.
Using the correct input type along with other input attributes (pattern, size, maxlength, required, etc.) utilizes HTML’s built-in validation features to help avoid input error: Read the MDN Web Docs on Form Data Validation
HTML Autocomplete Attributes
The autocomplete attributes are only for input fields collecting information
about the user. By using this autocomplete attribute, inputs can be auto-filled by the browser which makes it easier for everyone to fill out a form.
Add the appropriate
autocomplete attribute (and its corresponding
type attribute) to each form input field that requires user
Clearly identifying required fields helps prevent user errors and it reduces the chance that users will neglect to fill out all necessary fields in a form. The general requirements for identifying required fields are:
- The aria-required=”true” indicator or the HTML5 required attribute should be set on the input element.
- A supplemental visible indicator should be available to sighted users (we use a red asterisk).
The example below demonstrates the use of the autocomplete and required attributes. It also shows the style you can add for a required field, using class=”label-required” on the corresponding label element.
Focus order should be logical. Screen reader and keyboard users use the tab key to navigate the focusable/interactive elements on a page. The sequential order of those elements can help a user understand the page.
Labels, Instructions, and Fieldsets
HTML Label Element
Using the HTML label element explicitly is the preferred method when labeling form input fields. Example of using the HTML label element explicitly:
Using the HTML label element makes getting into the associated input field easier for users, as clicking on the label sends focus into that input field.
Input Field Instructions
A screen reader user may not hear non-focusable text inside a form if it is not programmatically associated with an input. Using aria-describedby allows for the programmatic association of the instructions to the input.
Groups of related form elements should be grouped together in fieldsets with legends. Example of using a fieldset and legend:
Although it is possible to create a group label with
<legend>, there is no easy way to create instructions that are associated with a group (adding
aria-describedby to either the
<legend> element doesn’t work). There are some ways
to do this:
- Add the instructions to the legend if they are short. Some screen readers will read the legend every time the user goes to a new form field in that group. If the legend is very long, this can be annoying.
- Associate the instructions with one of the fields (usually the first field is best) within the group, using aria-describedby. This way, the group instructions are only read once.
- Put the instructions before the start of the whole form. This is not the most ideal since the user may forget the instructions by the time they get to the group of fields they need instructions for.
Users need to know of any input errors or if their form submission was successful. We recommend using the constraint validation API to check the validity of the input values and creating custom error messages (do not use browser default error messages).
Options for implementing validation messages
- Upon form submission, send user focus to a validation message as a summary. The summary should include a count of errors so that users get a sense of the scope of the problem. The summary should also include a link to the first field that has an error. Ensure the summary container has a tabindex=”-1” and has an ARIA role=”alert”.
- Upon form submission, send user focus to the first input field with an error.
- Inline (live) validation of error messages. We discourage using this method since it is tricky to implement with timing the aria-live announcements of error messages.
Must haves for all error messages
- Set aria-invalid=”true” on input fields with errors.
- Associate error messages with form fields using aria-describedby so that screen reader users know how to fix the problem
- Ensure error messages are visible and adjacent to the inputs so that screen magnification users can easily see which messages belong to which fields.
If the form submission causes a new page to load (or the same page to reload):
- Update the page
<title>to reflect the error or success confirmation status. The title could say something like, “There were 2 errors in the form” or “Success! Your application has been submitted.” The page
<title>is the first thing screen reader users hear when the page loads, so it is the fastest way to give them feedback on the form submission status.
- Provide a quick way to reach the error or success message. For example, provide a “skip to main content” link that takes the users to the message.
Below is an example of validating user input and setting the focus to the first field with an error. For more examples of how to validate user input, check out: