How to group form fields
Short answer
Wrap related fields in <fieldset> and put the group title in <legend>:
<fieldset>
<legend>Delivery</legend>
<label><input type="radio" name="delivery" checked> Courier</label>
<label><input type="radio" name="delivery"> Pickup</label>
</fieldset>A screen reader announces the group name before reading the options: "Delivery, Courier". This matters especially for radio buttons and checkboxes — without a title it is unclear what the choice is about.
Styling
<fieldset> has a default border and padding. They change like on any block, and <legend> can be styled as a heading:
<style>
fieldset { display: grid; gap: 8px; max-width: 280px; padding: 12px 16px; border: 1px solid silver; border-radius: 10px; }
legend { padding: 0 6px; font-weight: 700; }
</style>
<fieldset>
<legend>Contacts</legend>
<input placeholder="Email">
<input placeholder="Phone">
</fieldset>Disabling the whole group
The disabled attribute on <fieldset> disables all the fields inside at once — handy when part of a form is not available yet:
<fieldset disabled>
<legend>Gift wrapping</legend>
<label><input type="checkbox"> Add a card</label>
</fieldset>Common mistake
The <fieldset> border is removed with border: none, and <legend> is removed along with it and replaced with a paragraph. It saves space visually, but the group loses its name for screen readers. Keep <legend>, even if you style it as plain text.
Functions used in this recipe
- <fieldset>, <legend> — A group of related form fields with a `<legend>` title.
- <form> — A form: collects data from its fields and sends it to the server.
- <label> — A label for a form field.
- disabled — Disables a form control: it cannot be used, and its value is not submitted.