We are still cooking the magic in the way!
Forms: Structure, Labels & Fieldsets
What Are HTML Forms?
Forms are how users send data to a server. Every login page, search bar, and contact form relies on the <form> element. A form collects input through text fields, dropdowns, and buttons, then submits that data for processing. In this lesson, you will learn to build accessible forms with proper labels, fieldsets, and semantic markup.
The form Element: action and method
The <form> element wraps all input controls. The action attribute specifies where data is sent, and method determines how. There are two methods:
- GET -- Appends data to the URL as query parameters (e.g.,
?search=html). Use GET for searches and filters where the URL should be shareable. Data is visible in the address bar. - POST -- Sends data in the HTTP request body, hidden from the URL. Use POST for logins, registrations, and forms that modify server data. No size limit, and data stays out of browser history.
Example: Basic Form with GET and POST
<!-- Search form using GET -->
<form action="/search" method="GET">
<label for="query">Search:</label>
<input type="text" id="query" name="query">
<button type="submit">Search</button>
</form>
<!-- Contact form using POST -->
<form action="/contact" method="POST">
<label for="email">Email:</label>
<input type="text" id="email" name="email">
<button type="submit">Send</button>
</form>
Labels: The Most Important Accessibility Feature
The <label> element associates a text description with a form control. This is essential for accessibility -- screen readers announce the label when a user focuses on the input, and clicking the label activates the associated control. There are two association methods:
Explicit labels use the for attribute, matching the id of the input. This is preferred because it works even when the label and input are not adjacent.
Implicit labels wrap the input inside the label element, requiring no for or id attributes.
Example: Explicit vs Implicit Labels
<!-- Explicit label (preferred) -->
<label for="username">Username:</label>
<input type="text" id="username" name="username">
<!-- Implicit label -->
<label>
Password:
<input type="text" id="password" name="password">
</label>
name attribute is what gets sent to the server. Without a name, the input data will not be included in the form submission. The id is used for label association and CSS targeting. Both serve different purposes and both are important.Grouping Controls with fieldset and legend
When a form has multiple related groups of inputs, use <fieldset> to group them and <legend> to give each group a title. This is especially important for radio buttons and checkboxes, where multiple inputs share a common question. Screen readers announce the legend before each input in the group, so users understand the context.
Example: Fieldset with Legend for Radio Buttons
<form action="/survey" method="POST">
<fieldset>
<legend>Personal Information</legend>
<label for="fullname">Full Name:</label>
<input type="text" id="fullname" name="fullname">
<label for="user-email">Email:</label>
<input type="text" id="user-email" name="email">
</fieldset>
<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="mail"> Mail
</label>
</fieldset>
<button type="submit">Submit Survey</button>
</form>
Textarea: Multi-Line Text Input
The <textarea> element creates a resizable multi-line text field for comments, messages, or descriptions. Unlike <input>, it is not self-closing -- text between the tags becomes the default value. Use rows and cols for initial sizing, though CSS is preferred for layout control.
Select, Option, and Optgroup: Dropdown Menus
The <select> element creates a dropdown list. Each choice is an <option>. For long lists, group related options with <optgroup>. The value attribute is sent to the server, while the text content is what users see.
Example: Textarea, Select, and Optgroup
<form action="/feedback" method="POST">
<label for="department">Department:</label>
<select id="department" name="department">
<option value="">-- Select a department --</option>
<optgroup label="Engineering">
<option value="frontend">Frontend</option>
<option value="backend">Backend</option>
</optgroup>
<optgroup label="Design">
<option value="ui">UI Design</option>
<option value="ux">UX Research</option>
</optgroup>
</select>
<label for="comments">Comments:</label>
<textarea id="comments" name="comments" rows="5" cols="40"></textarea>
<button type="submit">Send Feedback</button>
</form>
Button Types
The <button> element has three types that control its behavior:
- type="submit" -- Submits the form data to the server. This is the default type if no type is specified.
- type="reset" -- Clears all form fields back to their default values. Use this sparingly, as users rarely want to erase everything they have typed.
- type="button" -- Does nothing by default. Use this for JavaScript-driven actions that should not submit or reset the form.
type attribute on your buttons. A <button> without a type inside a form defaults to type="submit", which can cause accidental form submissions when users click buttons you intended for other purposes.Form Layout Patterns
HTML forms have no built-in layout -- labels and inputs appear inline by default. Use a wrapping <div> around each label-input pair and style with CSS. A stacked layout works best on mobile.
Example: Stacked Form Layout with CSS
<style>
.form-group {
margin-bottom: 16px;
}
.form-group label {
display: block;
margin-bottom: 4px;
font-weight: bold;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
</style>
<form action="/register" method="POST">
<div class="form-group">
<label for="name">Full Name:</label>
<input type="text" id="name" name="name">
</div>
<div class="form-group">
<label for="bio">Bio:</label>
<textarea id="bio" name="bio" rows="3"></textarea>
</div>
<button type="submit">Register</button>
</form>
<label> element. Placeholders are supplementary hints, not replacements for labels.Practice Exercise
Build a job application form with the following structure: Create a <fieldset> labeled "Personal Details" containing explicitly labeled text inputs for full name, email, and phone number. Create a second <fieldset> labeled "Job Preferences" containing a <select> dropdown with two <optgroup> groups (Engineering and Marketing, each with two or three role options), a group of radio buttons for employment type (Full-time, Part-time, Contract), and a <textarea> for a cover letter. Include a submit button with type="submit" and a reset button with type="reset". Ensure every input has a proper name attribute and the form uses method="POST".