Skip to content

FormsWarning: Draft

Forms can be simple or complex, and may be presented as dedicated pages, side panels, or modals depending on the use case and the situation.
Information:

We recommend using our Form control component to automatically handle accessibility for form controls. The guidelines on this page have been used to inform the implementation of our Telescope form components and should only be necessary to use outside of Telescope when creating custom form components.

To satisfy WCAG 4.2.1 ("For all user interface components, the name and role can be programmatically determined"), an input must be named.

An accessible name is a short string of text that’s programatically associated with a UI element. Its purpose is to help assistive technology users understand the UI element’s purpose and distinguish it from other UI elements on the page.

Information:

This is unrelated to the name attribute in HTML.

Use a <label> element and give its for attribute a value matching the form control’s id.

Information:

Avoid nesting form controls within a <label>. This works in theory, but assistive technology support for this pattern is inadequate.

<label for="expense-category">Expense category</label> <input type="text" id="”expense-category" />

Use aria-labelledby when the form control’s label is present in the markup but can't be changed to a <label> element, such as when it needs to be a <div> or <span>. Give the form control’s aria-labelledby attribute a value matching the label’s id attribute.

<span id="expense-category">Expense category</span>
<input type="text" aria-labelledby="expense-category" />
Information:

In general, avoid using aria-label to give form controls an accessible name.

Use aria-label when the form control’s label is not in the markup and you can’t add it to the markup. Or when the label is in the markup, but you can’t change it to a <label> element or use aria-labelledby to associate it with the form control.

In the latter case, make sure the visible label matches the value of the aria-label. Note, in addition to other issues with using aria-label, this means that screen reader users may hear the same label twice.

<span>Expense category</span> <input type="text" aria-label="Expense category" />

Without a visible label, it can be difficult for people to understand or remember what they should fill in or select. This especially impacts people with cognitive impairments.

It’s only acceptable to hide a visible label when a common design pattern is used in a context with visual cues that clarify the form control’s purpose. An example is a search field placed near the top of a page, featuring a magnifying glass icon and/or a button labelled “Search”.

Note, form controls without visible labels still need accessible names. We recommend using our VisuallyHidden component for this use case. Wrap it around a <label> with a for attribute matching the form control’s id.

<VisuallyHidden>
<label for="search-field">Search</label>
</VisuallyHidden>
<input type="search" id="search-field" />

Related form controls are form controls that share a theme or purpose. For example, a set of radio buttons to select the payment status of an expense. Or a group of text fields used to input an address (e.g., street, apartment number, city, zip code).

To provide an accessible name to related form controls, start by wrapping them in a <fieldset> element. Then, use the aria-labelledby attribute on the <fieldset> to reference the id of the text element that serves as the visible label.

<span id="payment-status">Payment status</span>
<fieldset aria-labelledby="payment-status">
<input type="checkbox" id="pending" />
<label for="pending">Pending</label>
<input type="checkbox" id="settled" />
<label for="settled">Settled</label>
<input type="checkbox" id="Refund" />
<label for="Refund">Refund</label>
</fieldset>

An accessible description is a text string that provides extra context about a UI element, helping assistive technology users to understand its purpose or requirements. Typically longer than an accessible name, it can include instructions or clarifications.

To provide a form control with an accessible description, use the aria-labelledby attribute on the <input> element (or <fieldset> for groups of related form controls) to reference the id of the text element containing the description.

<label for="password">Create a password</label>
<input type="password" id="password" aria-describedby="password-requirements" />
<p id="password-requirements">
Your password must be at least 8 characters long and include a mix of letters, numbers, and
special symbols.
</p>

To inform assistive technology users that a single form control is required, add aria-required=”true” to the form control.

<label for="name">Your name</label> <input type="text" id="name" aria-required="true" />
Information:

Avoid using required instead of aria-required=”true”, as some browser and screen reader pairings announce the form control as invalid before the user has started typing.

For a group of related form controls, mention it’s required in its accessible name.

<span id="expense-category">Expense category (select at least one)</span>
<fieldset aria-labelledby="expense-category">
<input type="checkbox" id="software" />
<label for="software">Software</label>
<input type="checkbox" id="travel" />
<label for="travel">Travel</label>
<input type="checkbox" id="training" />
<label for="training">Training</label>
</fieldset>
Information:

Avoid adding aria-required=”true” to a <fieldset> element. It only works with some browser and screen reader pairings. More importantly, it’s invalid, as aria-required should only be used on interactive elements and the <fieldset> element maps to the group role, which represent non-interactive document structure elements.

When a form control becomes invalid, assistive technology users need clear, accessible feedback to resolve the error.

  1. Add the aria-invalid attribute to the form control and set its value to “true”
  2. Add an error message after the form control and its optional description
  3. Add an aria-describedby attribute to the form control and an id to the error message. If aria-describedby is already being used, prepend the id of the error message, so the user first hears what's wrong and then hears the instructions from the hint text.
  4. Match the values of the aria-describedby and id attributes
  5. When the form control is no longer invalid, remove the aria-invalid attribute completely instead of setting it to “false”
<label for="password">Create a password</label>
<input
id="password"
aria-describedby="error password-requirements"
aria-required="true"
aria-invalid="true"
/>
<p id="password-requirements">
Your password must be at least 8 characters long and include a mix of letters, numbers, and
special symbols.
</p>
<p id="error">The password you entered is too short.</p>
Information:

Avoid using aria-errormessage, due to inconsistent support across browsers and screen readers (source 1, source 2), despite its semantic appropriateness.

If a user has tried to submit a form with a single invalid form control, mark it as invalid and provide it with an error message. Additionally, move the user’s focus to the invalid form control.

If multiple form controls are invalid, display an error summary at the top of the form. It should satisfy the following criteria:

  • Each error links to its corresponding invalid form control
  • The errors are worded the same as those next to the invalid form controls
  • The error summary has a descriptive heading
  • The user’s focus is moved to the error summary’s heading. (As the heading is not interactive, it’s not inherently focusable. To make it focusable without adding it to the natural tabbing order of the page, set its tabindex attribute to -1.)
  • Every invalid form control is marked as invalid and provided with an error message
<div>
<h2 tabindex="-1">Please correct the following 3 errors</h2>
<ul>
<li><a href="#full-name">Enter your full name</a></li>
<li><a href="#email">Enter your email address</a></li>
<li><a href="#address">Enter your address</a></li>
</ul>
</div>
Information:

Linking to invalid form controls is recommended by the W3C as an advisory technique to comply with WCAG Success Criteria 3.3.1 Error Identification (Level A) and 3.3.3 Error Suggestion (Level AA).

Information:

As our Forms guidelines state, only use live validation for longer forms and strict input fields. Also, validate on blur instead of during interaction with the form control.

Before the form control becomes invalid, make sure a container is present in the markup with role=”status”. The “status” role ensures that when content, such as an error message, gets added to the container, screen readers will announce it

<label for="password">Create a password</label>
<input id="password" aria-describedby="password-requirements" aria-required="true" />
<p id="password-requirements">
Your password must be at least 8 characters long and include a mix of letters, numbers, and
special symbols.
</p>
<div role="status"></div>

When the form control becomes invalid, add an error message to the role=”status” container. Also, follow the guidelines about marking the form control as invalid.

<label for="password">Create a password</label>
<input
id="password"
aria-describedby="error password-requirements"
aria-required="true"
aria-invalid="true"
/>
<p id="password-requirements">
Your password must be at least 8 characters long and include a mix of letters, numbers, and
special symbols.
</p>
<div role="status">
<p id="error">The password you entered is too short.</p>
</div>
This page is a draft. Its content is likely to change.