Fieldsets and legends are HTML elements designed to group related form controls together. They provide both visual organization and semantic structure, making forms more accessible and easier to understand. These elements are especially important for screen reader users and complex forms with multiple sections.
What Are Fieldsets?
A <fieldset> is a container that groups related form elements together. It creates a visual border around the grouped elements and provides semantic meaning to assistive technologies.
A <legend> provides a caption or title for the fieldset, appearing at the top of the border.
Basic Fieldset and Legend Syntax
<form>
<fieldset>
<legend>Personal Information</legend>
<label for="firstname">First Name:</label>
<input type="text" id="firstname" name="firstname">
<label for="lastname">Last Name:</label>
<input type="text" id="lastname" name="lastname">
<label for="email">Email:</label>
<input type="email" id="email" name="email">
</fieldset>
<button type="submit">Submit</button>
</form>Why Use Fieldsets?
Fieldsets provide several important benefits:
- Visual organization: Create clear sections in complex forms
- Accessibility: Screen readers announce the legend when entering the fieldset
- Semantic structure: Provide meaning about form relationships
- Grouping controls: Logically group related fields together
- Radio button groups: Essential for grouping radio button options
Grouping Radio Buttons and Checkboxes
Fieldsets are especially important for radio button and checkbox groups, providing context for the choices:
Radio Button Groups
<form>
<fieldset>
<legend>Select your preferred contact method:</legend>
<div>
<input type="radio" id="email" name="contact" value="email" required>
<label for="email">Email</label>
</div>
<div>
<input type="radio" id="phone" name="contact" value="phone" required>
<label for="phone">Phone</label>
</div>
<div>
<input type="radio" id="mail" name="contact" value="mail" required>
<label for="mail">Mail</label>
</div>
</fieldset>
</form>Checkbox Groups
<form>
<fieldset>
<legend>Select your interests (choose all that apply):</legend>
<div>
<input type="checkbox" id="sports" name="interests" value="sports">
<label for="sports">Sports</label>
</div>
<div>
<input type="checkbox" id="music" name="interests" value="music">
<label for="music">Music</label>
</div>
<div>
<input type="checkbox" id="reading" name="interests" value="reading">
<label for="reading">Reading</label>
</div>
<div>
<input type="checkbox" id="travel" name="interests" value="travel">
<label for="travel">Travel</label>
</div>
</fieldset>
</form>Multiple Fieldsets in a Form
Complex forms often need multiple fieldsets to organize different sections:
<form action="/register" method="post">
<h2>Registration Form</h2>
<!-- Personal Information Section -->
<fieldset>
<legend>Personal Information</legend>
<label for="fullname">Full Name:</label>
<input type="text" id="fullname" name="fullname" required>
<label for="dob">Date of Birth:</label>
<input type="date" id="dob" name="dob" required>
<label for="gender">Gender:</label>
<select id="gender" name="gender">
<option value="">Select...</option>
<option value="male">Male</option>
<option value="female">Female</option>
<option value="other">Other</option>
</select>
</fieldset>
<!-- Contact Information Section -->
<fieldset>
<legend>Contact Information</legend>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="phone">Phone:</label>
<input type="tel" id="phone" name="phone">
<label for="address">Address:</label>
<textarea id="address" name="address" rows="3"></textarea>
</fieldset>
<!-- Account Settings Section -->
<fieldset>
<legend>Account Settings</legend>
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
<label for="confirm-password">Confirm Password:</label>
<input type="password" id="confirm-password" name="confirm-password" required>
</fieldset>
<button type="submit">Register</button>
</form>Nested Fieldsets
You can nest fieldsets inside other fieldsets for hierarchical organization:
<form>
<fieldset>
<legend>Address Information</legend>
<!-- Billing Address -->
<fieldset>
<legend>Billing Address</legend>
<label for="bill-street">Street:</label>
<input type="text" id="bill-street" name="bill-street">
<label for="bill-city">City:</label>
<input type="text" id="bill-city" name="bill-city">
<label for="bill-zip">Zip:</label>
<input type="text" id="bill-zip" name="bill-zip">
</fieldset>
<!-- Shipping Address -->
<fieldset>
<legend>Shipping Address</legend>
<input type="checkbox" id="same-address" name="same-address">
<label for="same-address">Same as billing address</label>
<label for="ship-street">Street:</label>
<input type="text" id="ship-street" name="ship-street">
<label for="ship-city">City:</label>
<input type="text" id="ship-city" name="ship-city">
<label for="ship-zip">Zip:</label>
<input type="text" id="ship-zip" name="ship-zip">
</fieldset>
</fieldset>
</form>Disabling Entire Fieldsets
The disabled attribute on a fieldset disables all form controls inside it:
<form>
<fieldset>
<legend>Account Information</legend>
<label for="username">Username:</label>
<input type="text" id="username" name="username" value="johndoe">
<label for="email">Email:</label>
<input type="email" id="email" name="email" value="john@example.com">
</fieldset>
<!-- Disabled fieldset - all controls inside are disabled -->
<fieldset disabled>
<legend>Premium Features (Upgrade Required)</legend>
<input type="checkbox" id="feature1" name="feature1">
<label for="feature1">Advanced Analytics</label>
<input type="checkbox" id="feature2" name="feature2">
<label for="feature2">Priority Support</label>
<input type="checkbox" id="feature3" name="feature3">
<label for="feature3">Custom Branding</label>
</fieldset>
<button type="submit">Save Changes</button>
</form>Styling Fieldsets and Legends
CSS can be used to customize the appearance of fieldsets and legends:
<style>
fieldset {
border: 2px solid #e0e0e0;
border-radius: 8px;
padding: 20px;
margin-bottom: 24px;
background-color: #f9f9f9;
}
legend {
font-size: 18px;
font-weight: 600;
color: #333;
padding: 0 10px;
background-color: white;
}
/* Remove default border for modern look */
fieldset.modern {
border: none;
padding: 0;
margin: 0 0 24px 0;
background-color: transparent;
}
fieldset.modern legend {
font-size: 20px;
font-weight: bold;
color: #4CAF50;
padding: 0;
margin-bottom: 12px;
border-bottom: 2px solid #4CAF50;
display: block;
width: 100%;
}
/* Card-style fieldset */
fieldset.card {
border: none;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
border-radius: 8px;
padding: 24px;
background-color: white;
}
fieldset.card legend {
font-size: 20px;
color: #2c3e50;
padding: 0 0 12px 0;
}
/* Disabled fieldset styling */
fieldset:disabled {
opacity: 0.6;
background-color: #f5f5f5;
}
label {
display: block;
margin: 12px 0 4px 0;
font-weight: 500;
}
input, select, textarea {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
</style>
<form>
<!-- Default styled fieldset -->
<fieldset>
<legend>Personal Information</legend>
<label for="name1">Name:</label>
<input type="text" id="name1" name="name1">
</fieldset>
<!-- Modern styled fieldset -->
<fieldset class="modern">
<legend>Contact Details</legend>
<label for="email1">Email:</label>
<input type="email" id="email1" name="email1">
</fieldset>
<!-- Card styled fieldset -->
<fieldset class="card">
<legend>Preferences</legend>
<label for="newsletter">Newsletter:</label>
<select id="newsletter" name="newsletter">
<option>Weekly</option>
<option>Monthly</option>
</select>
</fieldset>
</form>Practical Examples
Survey Form
<form action="/submit-survey" method="post">
<h2>Customer Satisfaction Survey</h2>
<fieldset>
<legend>1. How would you rate our product?</legend>
<div>
<input type="radio" id="excellent" name="rating" value="5" required>
<label for="excellent">Excellent</label>
</div>
<div>
<input type="radio" id="good" name="rating" value="4" required>
<label for="good">Good</label>
</div>
<div>
<input type="radio" id="average" name="rating" value="3" required>
<label for="average">Average</label>
</div>
<div>
<input type="radio" id="poor" name="rating" value="2" required>
<label for="poor">Poor</label>
</div>
<div>
<input type="radio" id="terrible" name="rating" value="1" required>
<label for="terrible">Terrible</label>
</div>
</fieldset>
<fieldset>
<legend>2. What features do you use most? (Select all that apply)</legend>
<div>
<input type="checkbox" id="feature-a" name="features" value="feature-a">
<label for="feature-a">Feature A</label>
</div>
<div>
<input type="checkbox" id="feature-b" name="features" value="feature-b">
<label for="feature-b">Feature B</label>
</div>
<div>
<input type="checkbox" id="feature-c" name="features" value="feature-c">
<label for="feature-c">Feature C</label>
</div>
</fieldset>
<fieldset>
<legend>3. Additional Comments</legend>
<label for="comments">Tell us more about your experience:</label>
<textarea id="comments" name="comments" rows="5"></textarea>
</fieldset>
<button type="submit">Submit Survey</button>
</form>Payment Form
<form action="/process-payment" method="post">
<h2>Payment Information</h2>
<fieldset>
<legend>Billing Address</legend>
<label for="fullname">Full Name:</label>
<input type="text" id="fullname" name="fullname" required>
<label for="street">Street Address:</label>
<input type="text" id="street" name="street" required>
<div style="display: flex; gap: 10px;">
<div style="flex: 2;">
<label for="city">City:</label>
<input type="text" id="city" name="city" required>
</div>
<div style="flex: 1;">
<label for="state">State:</label>
<input type="text" id="state" name="state" required>
</div>
<div style="flex: 1;">
<label for="zip">Zip:</label>
<input type="text" id="zip" name="zip" required>
</div>
</div>
</fieldset>
<fieldset>
<legend>Payment Method</legend>
<div>
<input type="radio" id="credit" name="payment-method" value="credit" required>
<label for="credit">Credit Card</label>
</div>
<div>
<input type="radio" id="debit" name="payment-method" value="debit" required>
<label for="debit">Debit Card</label>
</div>
<div>
<input type="radio" id="paypal" name="payment-method" value="paypal" required>
<label for="paypal">PayPal</label>
</div>
</fieldset>
<fieldset>
<legend>Card Details</legend>
<label for="card-number">Card Number:</label>
<input type="text" id="card-number" name="card-number" required>
<div style="display: flex; gap: 10px;">
<div style="flex: 1;">
<label for="expiry">Expiry Date:</label>
<input type="text" id="expiry" name="expiry" placeholder="MM/YY" required>
</div>
<div style="flex: 1;">
<label for="cvv">CVV:</label>
<input type="text" id="cvv" name="cvv" maxlength="3" required>
</div>
</div>
</fieldset>
<button type="submit">Complete Payment</button>
</form>Job Application Form
<form action="/submit-application" method="post" enctype="multipart/form-data">
<h2>Job Application</h2>
<fieldset>
<legend>Personal Information</legend>
<label for="applicant-name">Full Name:</label>
<input type="text" id="applicant-name" name="applicant-name" required>
<label for="applicant-email">Email:</label>
<input type="email" id="applicant-email" name="applicant-email" required>
<label for="applicant-phone">Phone:</label>
<input type="tel" id="applicant-phone" name="applicant-phone" required>
</fieldset>
<fieldset>
<legend>Position Details</legend>
<label for="position">Position Applied For:</label>
<select id="position" name="position" required>
<option value="">Select a position</option>
<option value="developer">Software Developer</option>
<option value="designer">UI/UX Designer</option>
<option value="manager">Product Manager</option>
</select>
<label for="start-date">Available Start Date:</label>
<input type="date" id="start-date" name="start-date" required>
</fieldset>
<fieldset>
<legend>Work Authorization</legend>
<div>
<input type="radio" id="authorized-yes" name="authorized" value="yes" required>
<label for="authorized-yes">Yes, I am authorized to work</label>
</div>
<div>
<input type="radio" id="authorized-no" name="authorized" value="no" required>
<label for="authorized-no">No, I require sponsorship</label>
</div>
</fieldset>
<fieldset>
<legend>Documents</legend>
<label for="resume">Resume (PDF):</label>
<input type="file" id="resume" name="resume" accept=".pdf" required>
<label for="cover-letter">Cover Letter (PDF, optional):</label>
<input type="file" id="cover-letter" name="cover-letter" accept=".pdf">
</fieldset>
<button type="submit">Submit Application</button>
</form>Best Practices
Always Include a Legend
Every fieldset should have a legend for accessibility:
<!-- Good: Legend provides context -->
<fieldset>
<legend>Shipping Method</legend>
<input type="radio" id="standard" name="shipping" value="standard">
<label for="standard">Standard Shipping</label>
</fieldset>
<!-- Bad: No legend (confusing for screen readers) -->
<fieldset>
<input type="radio" id="standard" name="shipping" value="standard">
<label for="standard">Standard Shipping</label>
</fieldset>Use Descriptive Legends
Make legends clear and specific:
<!-- Good: Clear and descriptive -->
<fieldset>
<legend>Select your preferred payment method</legend>
<!-- radio buttons -->
</fieldset>
<!-- Bad: Too vague -->
<fieldset>
<legend>Payment</legend>
<!-- radio buttons -->
</fieldset>Group Related Fields Only
Only group fields that are logically related:
<!-- Good: Related fields grouped together -->
<fieldset>
<legend>Credit Card Information</legend>
<input type="text" name="card-number">
<input type="text" name="expiry">
<input type="text" name="cvv">
</fieldset>
<!-- Bad: Unrelated fields grouped -->
<fieldset>
<legend>Form Fields</legend>
<input type="text" name="name">
<input type="email" name="email">
<input type="text" name="favorite-color">
<input type="number" name="shoe-size">
</fieldset>Don't Overuse Fieldsets
Not every form needs fieldsets. Use them when grouping adds value:
<!-- Good: Simple form without fieldsets -->
<form>
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<label for="password">Password:</label>
<input type="password" id="password" name="password">
<button type="submit">Login</button>
</form>
<!-- Unnecessary: Fieldset adds no value here -->
<form>
<fieldset>
<legend>Login</legend>
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<label for="password">Password:</label>
<input type="password" id="password" name="password">
</fieldset>
<button type="submit">Login</button>
</form>Accessibility Considerations
- Always include a legend for every fieldset
- Use clear, descriptive legend text
- Screen readers announce the legend when entering a fieldset
- Fieldsets are especially important for radio button groups
- The legend should be the first child of the fieldset
- Don't hide legends with CSS (use proper styling instead)
- Use disabled attribute on fieldsets to disable all controls at once
- Test with screen readers to ensure fieldsets are announced properly
Key Takeaways
- Fieldsets group related form controls together
- Legends provide a title or caption for the fieldset
- Always include a legend for accessibility
- Fieldsets are essential for radio button and checkbox groups
- Multiple fieldsets can organize complex forms into sections
- The
disabledattribute disables all controls in a fieldset - Fieldsets can be nested for hierarchical organization
- Use CSS to customize fieldset appearance
What's Next?
Congratulations! You've completed the Forms - Part 2 (Advanced) section. The next topic will introduce you to Form Accessibility, where you'll learn best practices for making forms usable by everyone, including those using assistive technologies.