Forms system documentation
View documentation for the current forms library for VA.gov on the platform website.
Accessibility considerations for all form elements
Do not disable buttons
Normally, with regular form controls, it is best to fully remove anything the user can’t interact with or which serves no purpose. However, disabling a “button” to act as a guide to the level of form completion (i.e. you are not able to proceed to the next step until the form contains enough data) is a common anti-pattern.
Disabled buttons don’t explain what’s wrong
When buttons are inactive, some users– particularly those with cognitive disabilities- may not know how to activate them. Disabled buttons don’t explain what’s wrong. They communicate that something is off, but very often that is not enough information. As a result, users are left wondering what’s actually missing, and consequently are locked out entirely. For example, if someone were to type in a short acronym like “VA” to search and the button doesn’t become accessible, they may think the search field is broken.
In addition, disabled buttons can be unintentionally read out and accessed by mobile screen readers using touch controls.
What to do instead
While it is technically possible, we strongly discourage disabling buttons. Here are recommendations on how to handle specific interactions:
- Lack of required fields. When a user attempts to submit a form without entering all required form fields:
- Announce the error and shift focus to the first unfilled required form field.
- Properly indicate required form elements (the right thing will happen for you when you use the required property on form fields in the Design System).
- No longer valid options. If certain options in a form are no longer valid then there are two options:
- Replace the form elements that can no longer be changed with text representing the current value instead of the current value within a disabled input.
- Hide the form elements that are no longer valid.
Is it ever valid to disable a button?
Post-form submission or post-action it can be appropriate to disable the submit or action button as the system is in-between states and loading or taking action. This behavior is often seen on buttons that make a purchase or reservation to prevent the user from accidentally triggering the action multiple times.
How to group form controls
- Group each set of thematically related controls in a
fieldsetelement. Use the
legendelement as a heading within each one. The
legendelements make it easier for screen reader users to navigate the form.
- Use a single legend for fieldset (this is required). One example of a common use of
legendis a question with radio button options for answers. The question text and radio buttons are wrapped in a fieldset, with the question itself being inside the
- Embed multiple fieldsets and legends for more complex forms if the form is not broken in separate chapters.
- Keep your form inputs and labels arranged vertically along the same Y axis. This approach is ideal, from an accessibility standpoint, because of limited vision that makes it hard to scan from right to left.
Enter a number between 1 and 10.
In all cases, only show error validation messages or stylings after a user has interacted with a particular field.
In general, when there is an error on a form, a few things must happen.
- The form field and its corresponding
<label>are wrapped in a container with a class name of
usa-input-error. This will provide a thick border and padding to visual indicate an error message to users who might have difficulty perceiving contrast. It also changes the border of the input to red as a secondary indicator.
- An error message is placed between the label and the form field.
- The form field receives an
aria-describedbyattribute that references the
idof the error message.
<span class="sr-only">Error</span>to error messages alerts screen screen readers clearly that an error exists.
The HTML for a typical error is:
<span class="usa-input-error-message undefined" role="alert" id="file-input-149-error-message"> <span class="sr-only">Error</span> Error message </span>
When a detailed form input label is not enough to convey the meaning or purpose of the input, we have three options for including additional context:
Default hint text
This should be used in the case where the needed clarification is a little longer, but less than two sentences. These should ideally not wrap more than twice for a total of three lines.
Inline within the label
This should be used in the case where the needed clarification is very short.
With Additional info
Using the additional info component should only be done in cases where the needed clarification is long, complex, requiring more than two sentences or multiple paragraphs, or special formatting (bullet points, links, etc.).
We want to avoid this variation when possible. Use of this component for this purpose is a last resort when attempts at reducing the content have failed. If a field needs a lot of explanation, it should ideally be moved to a distinct page with explanation on the page itself.