Should I put input elements inside a label element?

Viewed 296587

Is there a best practice concerning the nesting of label and input HTML elements?

classic way:

<label for="myinput">My Text</label>
<input type="text" id="myinput" />

or

<label for="myinput">My Text
   <input type="text" id="myinput" />
</label>
14 Answers

From the W3's HTML4 specification:

The label itself may be positioned before, after or around the associated control.


<label for="lastname">Last Name</label>
<input type="text" id="lastname" />

or

<input type="text" id="lastname" />
<label for="lastname">Last Name</label>

or

<label>
   <input type="text" name="lastname" />
   Last Name
</label>

Note that the third technique cannot be used when a table is being used for layout, with the label in one cell and its associated form field in another cell.

Either one is valid. I like to use either the first or second example, as it gives you more style control.

If you include the input tag in the label tag, you don't need to use the 'for' attribute.

That said, I don't like to include the input tag in my labels because I think they're separate, not containing, entities.

Personally I like to keep the label outside, like in your second example. That's why the FOR attribute is there. The reason being I'll often apply styles to the label, like a width, to get the form to look nice (shorthand below):

<style>
label {
  width: 120px;
  margin-right: 10px;
}
</style>

<label for="myinput">My Text</label>
<input type="text" id="myinput" /><br />
<label for="myinput2">My Text2</label>
<input type="text" id="myinput2" />

Makes it so I can avoid tables and all that junk in my forms.

Both are correct, but putting the input inside the label makes it much less flexible when styling with CSS.

First, a <label> is restricted in which elements it can contain. For example, you can only put a <div> between the <input> and the label text, if the <input> is not inside the <label>.

Second, while there are workarounds to make styling easier like wrapping the inner label text with a span, some styles will be in inherited from parent elements, which can make styling more complicated.

3rd party edit

According to my understanding html 5.2 spec for label states that the labels Content model is Phrasing content. This means only tags whose content model is phrasing content <label> are allowed inside </label>.

Content model A normative description of what content must be included as children and descendants of the element.

Most elements that are categorized as phrasing content can only contain elements that are themselves categorized as phrasing content, not any flow content.

One thing you need to consider is the interaction of checkbox and radio inputs with javascript.

Using below structure:

<label>
  <input onclick="controlCheckbox()" type="checkbox" checked="checkboxState" />
  <span>Label text</span>
</label>

When user clicks on "Label text" controlCheckbox() function will be fired once.

But when input tag is clicked the controlCheckbox() function may be fired twice in some older browsers. That's because both input and label tags trigger onclick event attached to checkbox.

Then you may have some bugs in your checkboxState.

I've run into this issue lately on IE11. I'm not sure if modern browsers have troubles with this structure.

There are several advantages of nesting the inputs into a label, especially with radio/checkbox fields,

.unchecked, .checked{display:none;}
  label input:not(:checked) ~ .unchecked{display:inline;}
  label input:checked ~ .checked{display:inline;}
<label>
  <input type="checkbox" value="something" name="my_checkbox"/>
  <span class="unchecked">Not Checked</span>
  <span class="checked">Is Checked</span>
</label>

As you can see from the demo, nesting the input field first followed by other elements allows,

  • The text to be clicked to activate the field
  • The elements following the input field to be dynamically styled according to the status of the field.

In addition, HTML std allows multiple labels to be associated with an input field, however this will confuse screen readers and one way to get round this is to nest the input field and other elements within a single label element.

Related