Creating Accessible Forms
Advanced Form Labeling
Introduction
There are times when the <label> element falls short—it cannot be used to provide multiple labels for a single form control, or to associate a single label with multiple form controls. There are also times when there is not a visible text label to be associated to a form control. The majority of these labeling limitations can be overcome with three ARIA properties (aria-labelledby, aria-describedby, and aria-label) and a couple other techniques outlined on this page.
aria-labelledby
A <label> element indicates which form field it labels by referencing its id attribute value:
<label for="fname">
It declares, "I am a label for this control".
With aria-labelledby, the form field indicates which element labels it by referencing its id attribute:
<input aria-labelledby="fnamelabel">
The form control declares, "I am a control labeled by this element").
Handling Multiple Labels
Because elements in a page must all have unique id attribute values, a <label> can only point to the id of a single control - at most a one-to-one relationship between label and control. aria-labelledby, however, allows an element to be referenced as a label for multiple controls, and allows multiple elements to be referenced as labels for a single control. In short, aria-labelledby overcomes the 1 to 1 limitation of <label>.
The following is a simplified example of a table that might be used for data entry. Each table header functions as a visual label for the form controls in the column below it. There is only one visual label for multiple form controls. The <label> element cannot be used to associate this text to the multiple text boxes.
| Name | Age | Weight |
|---|---|---|
The HTML for the first header ("Name") is:
<th id="namelabel" scope="col">Name</th>
The HTML for the first text field within the table is:
<input type="text" name="name1" aria-labelledby="namelabel">
This labels the text box with the "Name" text in the table header. This aria-labelledby attribute could be added to all three Name fields, thus properly labeling all of them with one text item.
Building on this example, the table below has visual labels along the top and side - multiple visual labels for each control.
| Name | Office Number | Phone |
|---|---|---|
| Cyndi | ||
| Jared | ||
| Jonathan |
The HTML for the first field in this table is:
<input type="text" name="office1" aria-labelledby="cyndi officenum">
The cyndi and officenum values reference the ids of the "Cyndi" and "Office Number" table cells. A screen reader will read "Cyndi Office Number" when navigating into this field. The reading order of multiple labels is based on the order in which these values are specified.
As a general rule, if a single label is present for a single control, the <label> element should be used to reference it. These labels provide additional functionality - clicking on them sets focus to or activates the control. This is not available when using aria-labelledby.
If a control has both an associated <label> and aria-labelledby, the referenced aria-labelledby text will override and be read of instead of the associated <label>.
aria-describedby
There are times when a form includes information that isn't exactly a label but is important enough to be read by a screen reader when navigating to the form control. This additional information can be associated to the form field with the aria-describedby attribute. For example:
New password must be 8-15 characters and include letters and numbers
Here is the HTML:
<label for="resetpass">Reset Password:</label>
<input type="password" name="resetpass" id="resetpass" aria-describedby="newpass">
<br>
<span id="newpass">New password must be 8-15 characters and include letters and numbers</span>
Because there is a single label, <label> is used rather than aria-labelledby. As with aria-labelledby, the aria-describedby attribute points to the id of the element that contains the password requirements. A screen reader would read both the associated label(s) and then the associated description(s). Descriptions are sometimes read after a short pause. aria-describedby can also reference multiple elements - just separate the referenced id values with spaces.
- While the
aria-labelledbyoverrides the<label>,aria-describedbydoes not. This means thataria-describedbyshould only be used in addition to a label (e.g.,<label>or <inputaria-labelledby>), not in place of one. - The
aria-describedbyattribute can also be used to reference descriptions that appear as 'tooltips'. Tooltips should become visible to sighted keyboard users when the control has keyboard focus, not just when the user hovers or clicks with a mouse.
Invisible Labels
There are times when a text label for a form control does not make sense visually. The most common example is the "Search" field. Its location within the page, in conjunction with the Search button, makes its purpose clear to sighted users. Adding a visual text label would be overkill and could negatively impact the site design.
One of the following three techniques should be used when a visible label is not available:
title attribute
If a form field has a title attribute, but no <label>, the screen reader will read the title as if it were a label.
Here is the HTML for the form control:
<input id="s" type="text" name="s" title="Search Terms">
This technique will also cause a tooltip to appear when the user hovers over the field with a mouse, which could be distracting for some users.
aria-label
The aria-label attribute can also be used when there is no text label on the page.
<input id="s" type="text" name="s" aria-label="Search Terms">
Unlike aria-labelledby which must reference another element, aria-label contains the label text directly. As with aria-labelledby, aria-label will override any associated <label> elements.
- Only one of these recommendations should be implemented. Using two or more together (e.g., a hidden
<label>and a duplicatetitleattribute) can cause information to be repeated by a screen reader. - Placeholder text (e.g.,
<input type="text" placeholder="Search WebAIM">) is not a suitable label and should never be used in place of the above techniques.
Recap
- Use
<label>element when you can. It has excellent browser and screen reader support, and users can click on the label to select the associated form control. - Use
aria-labelledbyto overcome the 1:1 limitations of<label>. - Use
aria-describedbyin addition to a label when you need to associate descriptive text to the form control. - Use a hidden
<label>ortitleoraria-labelwhen a visible text label is not available.
