HTML forms

Fieldset and legend, explained.

<fieldset> groups related form fields, and <legend> gives the group its caption. They matter most for radio buttons and checkboxes, where the legend is the question. Here is how to use them, what they do for screen-reader users, and how to style them.

Updated 7 November 2026

The basic fieldset

HTML
<fieldset>
  <legend>Your details</legend>

  <label for="name">Name</label>
  <input id="name" name="name" autocomplete="name" />

  <label for="email">Email</label>
  <input id="email" type="email" name="email" autocomplete="email" />
</fieldset>
  • The legend comes first. It must be the fieldset’s first child to act as its caption.
  • Browsers draw a border around the group, with the legend sitting on the top edge. Both can be restyled or removed; see below.
  • Nothing extra is sent. A fieldset only groups fields: the fields inside it are sent as normal, and the legend is not sent.

Why the legend matters

For a radio group or checkbox group, the legend is the question and each label is an answer. When someone tabs into the group, screen readers announce the legend together with the option, so “Phone” is heard as an answer to “How should we contact you?”. Without it, they hear “Phone, radio button” and have to guess.

HTML
<fieldset>
  <legend>How should we contact you?</legend>
  <label><input type="radio" name="contact_by" value="Email" /> Email</label>
  <label><input type="radio" name="contact_by" value="Phone" /> Phone</label>
</fieldset>

Keep legends short, because some screen readers repeat them for every field in the group. A group of ordinary text fields with clear labels often does not need a fieldset at all; use one when the fields only make sense together, such as an address or a date split into parts.

Disable a whole group

The disabled attribute on a fieldset disables every field inside it at once. Disabled fields cannot be edited and are not sent with the form, which makes this a tidy way to switch an optional section on and off:

HTML
<label><input type="checkbox" id="add-billing" /> Use a different billing address</label>

<fieldset id="billing" disabled>
  <legend>Billing address</legend>
  <label for="billing-street">Street</label>
  <input id="billing-street" name="billing_street" autocomplete="billing street-address" />
</fieldset>

<script>
  document.querySelector('#add-billing').addEventListener('change', (event) => {
    document.querySelector('#billing').disabled = !event.target.checked;
  });
</script>

Remove the default styling

The default border, padding and margin are easy to remove. Add min-width: 0 as well: by default a fieldset grows to fit its widest content, so a long code sample or table inside it can push it wider than the page.

CSS
/* Remove the default box and spacing */
fieldset {
  border: 0;
  padding: 0;
  margin: 0;
  min-width: 0;   /* stops wide content stretching the fieldset */
}
legend { padding: 0; }

Style the border and legend

To keep a box but make it match your design, style the border and the legend directly:

CSS
fieldset {
  border: 1px solid #d9d7e6;
  border-radius: 12px;
  padding: 16px 20px 20px;
  margin: 0 0 24px;
  min-width: 0;
}
legend {
  padding: 0 6px;
  font-weight: 600;
}

To make the legend look like a heading inside the box instead of a label on its border, float it. This is a long-standing technique and works in every current browser:

CSS
/* Make the legend sit inside the box like a heading, instead of on the border */
legend {
  float: left;
  width: 100%;
  padding: 0;
  margin-bottom: 12px;
  font-size: 1.125rem;
  font-weight: 600;
}
legend + * { clear: both; }

Grid and flexbox layouts work on a fieldset in current browsers, so you can lay out the fields inside it like any other container.

A grouped form that sends

This contact form posts to Heartdove, which saves every message, emails you an alert and tracks it until it is delivered or bounces. The fieldsets only change how the form reads; every field inside them arrives as its own labelled field, such as “Contact by: Phone”.

contact.html
<form action="https://submit.heartdove.com/v1/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />

  <fieldset>
    <legend>Your details</legend>
    <label for="name">Name</label>
    <input id="name" type="text" name="name" autocomplete="name" required />
    <label for="email">Email</label>
    <input id="email" type="email" name="email" autocomplete="email" required />
  </fieldset>

  <fieldset>
    <legend>How should we contact you?</legend>
    <label><input type="radio" name="contact_by" value="Email" checked /> Email</label>
    <label><input type="radio" name="contact_by" value="Phone" /> Phone</label>
  </fieldset>

  <label for="message">Message</label>
  <textarea id="message" name="message" rows="5" required></textarea>

  <input type="checkbox" name="botcheck" tabindex="-1" autocomplete="off" style="display:none" />
  <button type="submit">Send message</button>
</form>

Replace YOUR_ACCESS_KEY with your key from a free Heartdove form. For more on the groups themselves, see radio buttons and checkboxes.

Questions

What is the difference between fieldset and legend?

fieldset is the container that groups related fields. legend is the caption for that group, and must be the first element inside the fieldset.

How do I remove the border from a fieldset?

Set border: 0 on the fieldset. Most designs also reset padding and margin to 0, and set min-width: 0 so wide content cannot stretch it.

Is the legend sent with the form?

No. Only the named fields inside the fieldset are sent. The legend is for people reading the form.

Do I need a fieldset for every form?

No. Use one for radio and checkbox groups, and for fields that only make sense together. A simple contact form with clearly labelled fields does not need one.

What does disabled do on a fieldset?

It disables every field inside the fieldset. Disabled fields cannot be changed and are not sent when the form is submitted.

Never lose another enquiry.

Connect your first form in a few minutes. Your existing design stays exactly as it is.