In forms <label> is a powerful element. Not only is it's purpose to describe the purpose of an element, but it has some awesome built in accessibility properties that other elements don't out of the box.

According to Mozilla Developer Network (MDN)...

The HTML <label> element represents a caption for an item in a user interface.

So for every visible form element you should have a corresponding <label> element too.

Label bad habits

Whether you're a form expert or just a beginner you've probably been guilty of some nasty habits.


Not labelling fields at all

<form>
    <input type="text" name="first_name" placeholder="First Name">
</form>
Bad Habit: Not even using a label!

Every visible field should have a corresponding label assigned to it. To able-sighted users it may be obvious what the field is for because of it's on-page context but for those using screen-readers it's going to make filling out your form much harder. Always include a label!


Using the wrong element to label fields

<form>
    <div>First Name</div>
    <input type="text" name="first_name">
</form>
Bad Habit: Not even using the correct label element!

Sometimes you're just quickly putting together a form after a day of using the <div> tag and the <label> simply slips your mind.

The label element comes with some great accessibility and usability properties built in that you simply can't get (without some hacking) from other elements. By using another elements, such as a <p> or <div>, you're needlessly removing those great features.

<form>
    <label>First Name</label>
    <input type="text" name="first_name">
</form>
Enhancement: Use the label element at the very least!

Not using the built-in for= attribute

<form>
    <label>First Name</label>
    <input type="text" name="first_name">
</form>
Bad Habit: No for attribute on the label

Screen readers will read elements on the page in the order they appear so if your label appears above the field it relates to it should offer very basic accessibility.

The label element has a built-in method for linking it directly to the form element it captions...

<form>
    <label for="first_name">First Name</label>
    <input type="text" name="first_name" id="first_name">
</form>
Enhancement: Assign the label to the input using for= and id=

Get into the habit of adding the for= attribute to every label you insert into a form and make a habit of ensuring that attribute links to the element the label captions.

By adding this attribute you improve a few things:

  1. The label is linked directly to the element it captions
  2. The label, when clicked, puts focus on the field it captions (for checkboxes it toggles the state)
  3. Screenreaders don't need to make assumptions about which label goes with which field
  4. You increase the clickable area of a field

How to do this

for= should contain the id= of the element it captions. So in my example above I've used first_name which is also the ID of the input below the label.

Remember that IDs should be unique on a page so ensure you don't have multiple fields with the same ID. If you do the label will only focus on the first instance.


Using labels to caption a collection of fields

<form>
    <label>Your marketing preferences</label>
    
    <input type="checkbox" name="allow_email">
    <span>Send me emails</span>
    
    <input type="checkbox" name="allow_post">
    <span>Send me letters by post</span>
    
    <input type="checkbox" name="allow_calls">
    <span>Call me on my telephone</span>
</form>
Bad Habit: Using a label to describe multiple options

There will be situations you come up against where you need to display multiple form elements for one type of input.

In the example above our form needs to ask the user what types of marketing they allow. Logically the label is used to title the options and then each option is listed one after another.

This is an accessibility nightmare - imagine that this is how the form is read by a screen-reader (a simplified example):

  1. Your marketing preferences
  2. Input field
  3. Send me emails
  4. Input field
  5. Send me letters by post
  6. Input field
  7. Call me on my telephone

The checkbox inputs and spans are not in the correct order, the spans are not linked to the corresponding input and alone it doesn't make any sense. Even looking at the syntax you can see the problem.

Break this habit by using the correct elements: Introducing <fieldset>!!

<form>
  <fieldset>
    <legend>Marketing preferences</legend>
    
    <input type="checkbox" id="allow_emails" name="allow_emails">
    <label for="allow_emails">Send me emails</label>
    
    <input type="checkbox" id="allow_post" name="allow_post">
    <label for="allow_post">Send me letters by post</label>
    
    <input type="checkbox" id="allow_calls" name="allow_calls">
    <label for="allow_calls">Call me on my telephone</label>
    
  </fieldset>
</form>
Enhancement: Use the field set element to group this set of fields 🤔

By changing the syntax and using <fieldset> element to group a... ahem... set of fields you improve the accessibility and usability of this small part of your form.

  1. The legend gives the group's options clear context
  2. Each checkbox has a corresponding label
  3. Each label is clickable and toggles the state of the checkbox
  4. Because labels are assigned to the fields it doesn't matter the order the label and input is shown.

Put care into your labels and users will love you

It's easy, with forms, to cut corners and forget about accessibility and usability. If you take the tiny bit of extra time to use labels correctly you can make the experience more inclusive.

Put care into your labels and users will love you

Once you start weeding out your bad habits your eyes will be opened to how bad forms across the web really are.

Some of the biggest companies in the world with the biggest budgets have terribly inaccessible forms - but with a little bit of effort 🧀 each one of us can make a difference 🧀.