HTML course menu
HTML Form Labels, fieldset and legend: Accessible Forms
Learn to connect labels to form fields with for and id or by wrapping, why placeholders are not labels, how to group related fields with fieldset and legend, and how to add hints with aria-describedby.
On this page
A form field without a label is a guessing game, especially for people using screen readers. HTML gives you <label> to name each field and <fieldset> with <legend> to name groups of fields.
Two ways to connect a label#
1. With for and id (most common):
<label for="phone">Mobile number</label>
<input type="tel" id="phone" name="phone">The for value must match the field's id exactly.
2. By wrapping the field:
<label>Mobile number <input type="tel" name="phone"></label>Both connect the label to the field. The first is more flexible for layout because the label and field can be placed anywhere. Try clicking the label text in this result:
<p>
<label for="agree">I agree to the terms</label>
<input type="checkbox" id="agree" name="agree">
</p>
<p>
<label><input type="checkbox" name="news"> Send me the newsletter</label>
</p>Clicking either label ticks its checkbox. On phones, this makes small controls much easier to tap.
Placeholders are not labels#
<!-- Not enough -->
<input type="email" name="email" placeholder="Email">
<!-- Good -->
<label for="email2">Email</label>
<input type="email" id="email2" name="email" placeholder="name@example.com">A placeholder disappears as soon as you start typing, so users forget what the field was for. Placeholder text is also usually low-contrast and not reliably announced by every screen reader. Use a real label, and a placeholder only for an example value, if at all.
Grouping with fieldset and legend#
<fieldset> groups related fields and <legend> names the group. This is essential for radio buttons and checkboxes, where each option's label ("Yes", "No") makes no sense without the question:
<form>
<fieldset>
<legend>Preferred contact method</legend>
<label><input type="radio" name="contact" value="email"> Email</label>
<label><input type="radio" name="contact" value="phone"> Phone</label>
<label><input type="radio" name="contact" value="whatsapp"> WhatsApp</label>
</fieldset>
<fieldset>
<legend>Delivery address</legend>
<p><label for="street">Street</label> <input id="street" name="street"></p>
<p><label for="pin">PIN code</label> <input id="pin" name="pin" inputmode="numeric"></p>
</fieldset>
</form>Screen readers announce the legend along with each option, for example "Preferred contact method, Email, radio button". Browsers draw a border around each fieldset by default; change it with CSS.
A disabled attribute on a <fieldset> disables every field inside it.
Hints and help text#
To attach extra help text to a field, give the text an id and point to it with aria-describedby:
<label for="password">Password</label>
<input type="password" id="password" name="password" aria-describedby="password-hint">
<p id="password-hint">At least 12 characters. Use a mix of words and numbers.</p>Screen readers read the label first, then the hint. You will meet more ARIA in ARIA Basics.
Practice#
Practice exercise
Build a fieldset with the legend "Which languages do you know?" containing labelled checkboxes for HTML, CSS and JavaScript, plus a separately labelled text field "Other languages" with the hint "Separate with commas" connected by aria-describedby.
Show solution
<fieldset>
<legend>Which languages do you know?</legend>
<label><input type="checkbox" name="lang" value="html"> HTML</label>
<label><input type="checkbox" name="lang" value="css"> CSS</label>
<label><input type="checkbox" name="lang" value="js"> JavaScript</label>
</fieldset>
<p>
<label for="other">Other languages</label>
<input id="other" name="other" aria-describedby="other-hint">
</p>
<p id="other-hint">Separate with commas.</p>Key takeaway#
Finished this lesson?