fieldset and legend
Group related form controls with fieldset/legend — radio groups, disabled fieldsets, and accessible naming for control sets.
- html
- fieldset
- forms
<fieldset> groups related controls; <legend> captions that group. Assistive tech announces the legend with each control in the set, which is the correct pattern for radio groups and multi-part questions.
Docs: MDN <fieldset>, <legend>, WAI forms.
Radio group (canonical)
<fieldset>
<legend>Shipping method</legend>
<div class="choice">
<input type="radio" id="ship-standard" name="shipping" value="standard" checked />
<label for="ship-standard">Standard (3–5 days)</label>
</div>
<div class="choice">
<input type="radio" id="ship-express" name="shipping" value="express" />
<label for="ship-express">Express (1–2 days)</label>
</div>
</fieldset>
- Same
nameon radios → one selection. - Legend names the question; label names each option.
- Don’t replace this with a lone
div+aria-labelunless you know why.
Checkbox groups and address blocks
<fieldset>
<legend>Notify me about</legend>
<label><input type="checkbox" name="notify" value="product" /> Product updates</label>
<label><input type="checkbox" name="notify" value="blog" /> Blog posts</label>
</fieldset>
<fieldset>
<legend>Billing address</legend>
<label for="line1">Address line 1</label>
<input id="line1" name="line1" autocomplete="billing address-line1" />
<!-- more fields -->
</fieldset>
disabled fieldset
<fieldset disabled>
<legend>Enterprise options</legend>
<!-- all controls inside disabled -->
</fieldset>
Disabling the fieldset disables its descendants (with some historical quirks on legacy browsers). Useful for “upgrade to unlock” sections.
Styling without breaking a11y
fieldset {
border: 1px solid var(--border);
border-radius: 0.5rem;
padding: 1rem 1rem 0.75rem;
margin: 0;
min-inline-size: 0;
}
legend {
padding-inline: 0.35rem;
font-weight: 600;
}
Avoid display: contents on fieldset/legend in older engines — it historically broke accessibility mappings. Test if you reset fieldset display aggressively.
Nested fieldsets
Allowed but easy to over-nest. Prefer flatter forms; nest only when subgroups are real (e.g., “Card details” inside “Payment”).
Interview out-loud
“fieldset groups related controls and legend provides the group’s accessible name — essential for radio questions. Shared name on radios handles mutual exclusion. I can disable a whole group with disabled on the fieldset. I style carefully so legend semantics remain intact.”
Footguns
- Using a heading instead of legend for radio groups (weaker association).
- Empty legend or legend far from controls visually without structure.
- Forgetting shared
nameon radios. display: contentson fieldset breaking AT in some browsers.- Disabling fieldset and wondering why submit buttons inside won’t click — intentional.
Error messaging for groups
<fieldset aria-describedby="shipping-error" aria-invalid="true">
<legend>Shipping method</legend>
<!-- radios -->
<p id="shipping-error" class="error" role="alert">Choose a shipping method.</p>
</fieldset>
Associate group-level errors with the fieldset via aria-describedby. Focus the first radio on submit if invalid. Individual fields still need their own labels.
Styling legend
Legends are awkward to lay out historically. Prefer simple left-aligned legends over absolute positioning that breaks zoom. If you visually hide a legend, provide another accessible name — do not remove the legend without a replacement.
Checkbox lists vs radiogroups
Radios require a shared name and almost always a fieldset/legend question. Checkbox lists may use a fieldset when the group is a multi-select answer to one question (“Notify me about”). Independent settings toggles can be separate labeled checkboxes without a fieldset. Choose based on whether the controls form one question or many unrelated prefs.
<fieldset>
<legend>Add-ons</legend>
<label><input type="checkbox" name="addon" value="gift" /> Gift wrap</label>
<label><input type="checkbox" name="addon" value="rush" /> Rush handling</label>
</fieldset>
Related
- Forms labels and inputs
- Form validation attributes
- Accessible forms errors
- Autocomplete and name attributes
Further reading
Related guides
- Autocomplete and Name Attributesname and autocomplete on form fields — password managers, autofill tokens, and why missing names break real users more than demos.
- Form Validation AttributesNative constraint validation — required, type, pattern, min/max, minlength/maxlength, and wiring :invalid with accessible errors.
- Forms, Labels, and InputsWire labels to controls correctly, choose input types, group fields, and avoid the accessibility bugs that fail real users and audits.
- Accessibility Tree OverviewHow browsers build the accessibility tree from DOM and CSS — roles, names, states, what’s pruned, and how to inspect it in DevTools.
- Audio and Video ElementsNative audio/video — controls, sources, captions, autoplay policies, and accessibility requirements for media on the web.