Christian Heilmann

A quick reminder on how and why to use labels in forms to make them more accessible

Friday, December 4th, 2015 at 1:20 am

Yesterday the excellent Alice Boxhall of the Google Chrome team pointed out an annoying bug to me:

Seen in the wild on https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer … @codepo8

It seems the UserVoice page of Microsoft Edge has a checkbox that is inaccessible to screen reader users. The reason is a wrong implementation of a label. So, here is a quick reminder of how to use labels in plain HTML (without any ARIA extras) and why that’s a good idea.

Labels are there to connect an explanatory text with a form element. For a sighted user this can seem redundant – after all, the text is right next to the element. But once you use a screen reader you see that by not using labels, you make it impossible for people to use your forms.

The markup used in this demo is the following:

<div>
  <input type="checkbox" name="wombat"> 
  Yes, I want to buy a wombat!
</div>
<div>
  <label>
    <input type="checkbox" name="quokka">
    Yes, I want to buy a quokka!
  </label>
</div>
<div>
  <input type="checkbox" id="yayforwallaby" 
         name="wallaby">
  <label for="yayforwallaby">
    Yes, I want to buy a wallaby!
  </label>
</div>

On my Mac, using the in-built VoiceOver and Firefox, it is easy to test. Simply turn on VoiceOver Command+Fn+F5 and navigate using your keyboard by tabbing into the document. Here’s what that looks and sounds like:

In addition to the benefits for screenreaders, labels also make it easier for mouse or touch users to interact with your content. The following GIF shows that the options having labels enable the user to either click the tiny checkbox or the much larger text to check and uncheck.

showing how checkboxes with labels make the text clickable

Using labels isn’t hard. The simplest way is to nest the form element and the text inside the label:

  <label>
    <input type="checkbox" name="quokka">
    Yes, I want to buy a quokka!
  </label>

If you can’t do that, you need to connect the label and the form element using a for/id pairing. Remember, a form element’s id has no meaning to the form. The data sent to the server is what’s defined in the name attribute. The id is only good for scripting, CSS and as a fragment identifier/anchor. The following example shows how to connect the form element and the label:

<input type="checkbox" id="yayforwallaby" 
       name="wallaby">
<label for="yayforwallaby">
  Yes, I want to buy a wallaby!
</label>

This is what’s broken in the UserVoice example: there is a for attribute on the label, but the form element has no id. Hence there is no connection between the two and the label becomes redundant.

Quick aside: if you wanted to write a test for that, remember that the for attribute in HTML elements can not be accessed as element.for as for is a reserved word. It needs to be htmlFor.

As a way to catch the mistake in the sign-up form, you could do the following:

var labels = document.querySelectorAll('label');
for (var i=0; i<labels.length; i++) {
  if (labels[i].htmlFor) {
    if (!document.getElementById(labels[i].htmlFor)) {
      labels[i].style.background = 'firebrick';
    }
  }
}

Now, go forth and label the web!

Updates

Share on Mastodon (needs instance)

Share on Twitter

Newsletter

Check out the Dev Digest Newsletter I write every week for WeAreDevelopers. Latest issues:

Dev Digest 146: 🥱 React fatigue 📊 Query anything with SQL 🧠 AI News

Why it may not be needed to learn React, why Deepfake masks will be a big problem and your spirit animal in body fat! 

Dev Digest 147: Free Copilot! Panel: AI and devs! RTO is bad! Pi plays!

Free Copilot! Experts discuss what AI means for devs. Don't trust containers. Mandated RTO means brain drain. And Pi plays Pokemon!

Dev Digest 148: Behind the scenes of Dev Digest & end of the year reports.

In 50 editions of Dev Digest we gave you 2081 resources. Join us in looking back and learn about all the trends this year.

Dev Digest 149: Wordpress break, VW tracking leak, ChatGPT vs Google.

Slowly starting 2025 we look at ChatGPT vs Google, Copilot vs. Cursor and the state of AI crawlers to replace web search…

Dev Digest 150: Shifting manually to AI.

Manual coding is becoming less of a skill. How can we ensure the quality of generated code? Also, unpacking an APK can get you an AI model.

My other work: