Labelling controls

Best practices for labeling controls

Form controls include text fields, file-select fields, checkboxes, radio buttons, and drop-down lists.

Follow these best practices for labeling controls:

  • Provide labels to describe the purpose of the form control.
  • Use the <label> element.
  • Match exactly the for attribute of the label with the id attribute of the form control to explicitly associate them.
  • Elements that use explicitly associated labels are:
    • input type="text"
    • input type="checkbox"
    • input type="radio"
    • input type="file" (file-select fields)
    • input type="password"
    • textarea
    • select (drop-down lists)
  • Do not use the <label> element for the following elements.
    • Submit and Reset buttons (input type="submit" or input type="reset")
      • Label provided by the value attribute
    • Image buttons (input type="image")
      • Label provided by the alt attribute
    • Hidden input fields (input type="hidden")
    • Buttons (button elements or <input type="button">)
      • Label provided by the element content itself (<button>text</button>) or the value, aria-label, or aria-labelledby attribute.
  • Use ARIA labels (aria-labelledby and aria-label attributes) when it is not possible to use <label>
  • When using ARIA labels, include any visible text in the control label.
  • Use the aria-labelledby attribute to retrieve a label from the context, drawing on one or more elements in the context.
  • Avoid using the title attribute to identify form controls. It is not widely supported by assistive technology.
  • Keep label text short and concise.
  • Use unique label values on a page.
  • Position labels visually to the right of radio buttons and checkboxes.
  • Position labels visually directly above their form fields (preferred by WET) or to the left (WET alternative, when there’s a need to conserve vertical space).

  Good example: Associating labels explicitly using for/id attributes

Use the <label> element to associate text with form elements explicitly, whenever possible. The for attribute of the label must exactly match the id of the form control. Prioritize using the HTML <label> element to name form controls over using an ARIA label.

HTML

<div class="form-group">
   <label for="firstname">First name</label>
   <input type="text" name="firstname" id="firstname">
</div>
<div class="form-group">
   <input type="checkbox" name="married" id="married">
   <label for="married">Married</label>
</div>

  Good example: Visually hiding the label element

Visually hide the <label> element to avoid redundancy for users who can identify the purpose visually. In this example, the WET class .wb-inv effectively hides the label "Search" from sighted users but the element is still in the HTML and is encountered by assistive technology users.

HTML

<label for="search" class="wb-inv">Search</label> 
<input type="text" name="search" id="search"> 
<button type="submit">Search</button>

CSS

.wb-inv {
   clip: rect(1px,1px,1px,1px);
   height: 1px;
   margin: 0;
   overflow: hidden;
   position: absolute;
   width: 1px;
}

Use the WET class .wb-inv to visually-hide an element, as per the WET style guide: Invisible and visible content.

  Good example: Using aria-label

Use an aria-label attribute to name form inputs and other controls directly with non-visual text. This approach should only be used when the label of the control is clear from the surrounding content. The information in aria-label is not displayed visually.

In this example, a search input field needs no visual label since the submit button right beside it is labelled "Search". Since non-sighted users encounter content linearly, reading the input field before the button, we name the input field with the aria-label attribute.

HTML

<input type="text" name="search" aria-label="Search">  
<button type="submit">Search</button>

 Good example: Using aria-labelledby to concatenate a label from several sources

A <label> can only point to one form control. With aria-labelledby, one element can help label multiple form controls, and one form control can be labelled by multiple elements.

Use an aria-labelledby attribute to identify form inputs and other controls with names retrieved from surrounding elements. This approach should only be used when the label of the control is clear from the surrounding content.

In this example, each service is accompanied by an “Add to cart” button. An aria-labelledby attribute distinguishes the buttons from one another by concatenating a name out of the button itself and the preceding heading (e.g., “Add to cart Service 1”). The aria-labelledby attribute holds the id attribute values of the elements with the descriptive names. As this example illustrates, the aria-labelledby attribute can construct a name partially from its own native element name.

Service 1

[descriptive paragraph]

Service 2

[descriptive paragraph]

Service 3

[descriptive paragraph]

HTML

<h3 id="service1">Service 1</h3>
<p>[descriptive paragraph]</p>
<button id="add1" aria-labelledby="add1 service1" type="submit">
   Add to cart
</button>

<h3 id="service2">Service 2</h3>
<p>[descriptive paragraph]</p>
<button id="add2" aria-labelledby="add2 service2" type="submit">
   Add to cart
</button>

<h3 id="service3">Service 3</h3>
<p>[descriptive paragraph]</p>
<button id="add3" aria-labelledby="add3 service3" type="submit">
   Add to cart
</button>

  Good example: Using aria-labelledby to concatenate a label from several sources

In the example below, the text inputs use aria-labelledby to reference the row header and column header cells.

Office and phone numbers
Name Office Number Phone
Cyndi
Jared
Jonathan
View HTML
<table>
   <thead>
      <tr>
         <th scope="col">Name</th>
         <th id="officenum" scope="col">Office Number</th>
         <th id="phonelabel" scope="col">Phone</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <th id="cyndi" scope="row">Cyndi</th>   
         <td>
            <input type="text" size="4" name="office1" aria-labelledby="cyndi officenum">
         </td>
         <td>
            <input type="text" size="12" name="phone1" aria-labelledby="cyndi phonelabel">
         </td>
      </tr>
      <tr>
         <th id="jared" scope="row">Jared</th>
         <td>
            <input type="text" size="4" name="office2" aria-labelledby="jared officenum">
         </td>
         <td>
            <input type="text" size="12" name="phone2" aria-labelledby="jared phonelabel">
         </td>
      </tr>
      <tr>
         <th id="jon" scope="row">Jonathan</th>
         <td>
            <input type="text" size="4" name="office3" aria-labelledby="jon officenum">
         </td>
         <td>
            <input type="text" size="12" name="phone3" aria-labelledby="jon phonelabel">
         </td>
      </tr>
   </tbody>
</table>

  Good example: Labelling buttons

The <button> element creates a clickable button. Within the button element content, you can put text and tags like <i>, <b>, <strong>, <br>, <img>, etc.

You can also use the <input> element to create buttons, in which case the label is set in the value attribute of the element.

If you use <input type="image">, the label is set in the alt attribute.

HTML

<button type="submit">Submit</button> 
<button type="button">Cancel</button> 
<button>Activate</button>

<input type="submit" value="Submit"> 
<input type="button" value="Cancel">
<input type="image" src="searchbutton.jpg" alt="Search">

  Good example: Labelling image button using the aria-label attribute

In this example, an aria-label attribute names the button, rather than the child <img> element’s alt attribute. The alt attribute is set to null (empty): alt="".

HTML

<button aria-label="Next">
   <img src="images/next.png" alt="">
</button>

Related WCAG resources

Related WCAG resources

Success criteria

Techniques

Failures

Back to top