Master HTML forms completely — form element, all input types (text, email, password, number, date, checkbox, radio, file), textarea, select, fieldset, legend, labels, built-in validation, and form accessibility.
Forms are how users interact with your website — login pages, registration forms, search boxes, contact forms, payment flows. HTML provides a rich set of form elements that handle user input, validation, and submission.
Labels — Essential for Accessibility
Every input must have a <label>. Labels tell users what the field is for and, when clicked, focus the associated input.
<!-- Method 1: for/id association (most common) -->
<label for="username">Username</label>
<input type="text" id="username" name="username">
<!-- Method 2: wrapping the input -->
<label>
Email Address
<input type="email" name="email">
</label>
Why labels matter:
- Screen readers announce the label when the input is focused
- Clicking the label focuses the input — larger click target
- Required by WCAG accessibility guidelines
- Users with cognitive disabilities need clear field labels
<!-- ❌ No label — inaccessible -->
<input type="text" placeholder="Enter name">
<!-- ✅ Proper label -->
<label for="name">Full Name</label>
<input type="text" id="name" name="name" placeholder="e.g., Rahul Sharma">
Text Inputs
<!-- Single-line text -->
<label for="name">Full Name</label>
<input type="text" id="name" name="name"
placeholder="Rahul Sharma"
value=""
maxlength="100"
autocomplete="name">
<!-- Password (hides input) -->
<label for="password">Password</label>
<input type="password" id="password" name="password"
minlength="8"
autocomplete="current-password">
<!-- Email (validates format, keyboard shows @ on mobile) -->
<label for="email">Email Address</label>
<input type="email" id="email" name="email"
placeholder="you@example.com"
autocomplete="email">
<!-- URL -->
<label for="website">Website</label>
<input type="url" id="website" name="website"
placeholder="https://example.com">
<!-- Phone (shows numeric keyboard on mobile) -->
<label for="phone">Phone Number</label>
<input type="tel" id="phone" name="phone"
placeholder="+91 98765 43210"
pattern="[+]?[0-9]{10,15}">
<!-- Search (may show clear button on some browsers) -->
<input type="search" name="q" placeholder="Search..." aria-label="Search">
<!-- Number -->
<label for="quantity">Quantity</label>
<input type="number" id="quantity" name="quantity"
min="1" max="100" step="1" value="1">
<!-- Range (slider) -->
<label for="volume">Volume: <output id="vol-output">50</output></label>
<input type="range" id="volume" name="volume"
min="0" max="100" step="5" value="50"
oninput="document.getElementById('vol-output').value = this.value">
<!-- Date -->
<label for="dob">Date of Birth</label>
<input type="date" id="dob" name="dob"
min="1900-01-01" max="2010-12-31">
<!-- Time -->
<label for="meeting-time">Meeting Time</label>
<input type="time" id="meeting-time" name="meeting-time"
min="09:00" max="18:00">
<!-- DateTime-local -->
<label for="appointment">Appointment</label>
<input type="datetime-local" id="appointment" name="appointment">
<!-- Month -->
<label for="exp-month">Card Expiry</label>
<input type="month" id="exp-month" name="exp-month">
<!-- Week -->
<label for="week">Report Week</label>
<input type="week" id="week" name="week">
<!-- Color picker -->
<label for="theme-color">Theme Colour</label>
<input type="color" id="theme-color" name="theme-color" value="#4285f4">
Checkboxes — Multiple Selection
<fieldset>
<legend>Select your interests:</legend>
<label>
<input type="checkbox" name="interests" value="html" checked>
HTML
</label>
<label>
<input type="checkbox" name="interests" value="css">
CSS
</label>
<label>
<input type="checkbox" name="interests" value="javascript">
JavaScript
</label>
<label>
<input type="checkbox" name="interests" value="python">
Python
</label>
</fieldset>
<fieldset>
<legend>What is your experience level?</legend>
<label>
<input type="radio" name="experience" value="beginner" checked>
Beginner (0-1 years)
</label>
<label>
<input type="radio" name="experience" value="intermediate">
Intermediate (1-3 years)
</label>
<label>
<input type="radio" name="experience" value="experienced">
Experienced (3+ years)
</label>
</fieldset>
Key rules:
- All radio buttons in a group share the same
name — this makes them mutually exclusive - Checkboxes with the same
name allow multiple selections <fieldset> + <legend> groups related controls and is important for accessibility
Select Dropdowns
<!-- Basic dropdown -->
<label for="country">Country</label>
<select id="country" name="country">
<option value="">— Select country —</option>
<option value="IN" selected>India</option>
<option value="US">United States</option>
<option value="GB">United Kingdom</option>
<option value="AU">Australia</option>
</select>
<!-- Multiple selection -->
<label for="skills">Skills (hold Ctrl to select multiple)</label>
<select id="skills" name="skills" multiple size="5">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
<option value="react">React</option>
<option value="node">Node.js</option>
</select>
<!-- Option groups -->
<label for="course">Course</label>
<select id="course" name="course">
<optgroup label="Programming">
<option value="html">HTML Complete Guide</option>
<option value="js">JavaScript Master Course</option>
<option value="python">Python Master Course</option>
</optgroup>
<optgroup label="Computer Science">
<option value="dsa">Data Structures & Algorithms</option>
<option value="os">Operating Systems</option>
<option value="dbms">DBMS</option>
</optgroup>
</select>
Textarea
<label for="message">Message</label>
<textarea
id="message"
name="message"
rows="5"
cols="50"
placeholder="Write your message here..."
maxlength="500"
></textarea>
<textarea> is for multi-line text. Unlike <input>, it uses opening and closing tags, and default content goes between them (not in value).
File Upload
<!-- Single file -->
<label for="resume">Upload Resume (PDF)</label>
<input type="file" id="resume" name="resume" accept=".pdf">
<!-- Multiple files -->
<label for="photos">Upload Photos</label>
<input type="file" id="photos" name="photos" accept="image/*" multiple>
<!-- Important: form must have enctype for file uploads -->
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="document">
<button type="submit">Upload</button>
</form>
<!-- Hidden field — passes data without showing it to user -->
<input type="hidden" name="csrf_token" value="abc123xyz">
<input type="hidden" name="user_id" value="42">
<!-- Submit button -->
<button type="submit">Create Account</button>
<!-- Reset button (clears all fields) -->
<button type="reset">Clear Form</button>
<!-- Button with no default action (used with JavaScript) -->
<button type="button" onclick="showPreview()">Preview</button>
<!-- Image as submit button -->
<input type="image" src="submit-btn.png" alt="Submit form" width="100" height="40">
HTML5 has powerful built-in validation — no JavaScript needed for basic checks:
<form novalidate> <!-- Remove for real-world use to enable validation -->
<!-- Required field -->
<input type="text" name="name" required>
<!-- Minimum and maximum length -->
<input type="text" name="username" minlength="3" maxlength="20" required>
<!-- Numeric range -->
<input type="number" name="age" min="18" max="120" required>
<!-- Pattern matching (regex) -->
<input type="text" name="pincode"
pattern="[0-9]{6}"
title="Enter a valid 6-digit PIN code">
<!-- Email format -->
<input type="email" name="email" required>
<!-- URL format -->
<input type="url" name="website">
</form>
Validation Attributes Summary
| Attribute | Elements | Purpose |
|---|
required | All inputs | Field cannot be empty |
minlength | text, search, url, email, tel, textarea | Minimum character count |
maxlength | Same | Maximum character count |
min | number, date, range | Minimum value |
max | number, date, range | Maximum value |
pattern | text, search, url, tel, email | Regex pattern match |
type="email" | input | Validates email format |
type="url" | input | Validates URL format |
step | number, date, range | Valid increment |
Fieldset and Legend
Group related form fields with <fieldset> and label the group with <legend>:
<form action="/register" method="POST">
<fieldset>
<legend>Personal Information</legend>
<label for="first-name">First Name</label>
<input type="text" id="first-name" name="first_name" required>
<label for="last-name">Last Name</label>
<input type="text" id="last-name" name="last_name" required>
<label for="dob">Date of Birth</label>
<input type="date" id="dob" name="dob" required>
</fieldset>
<fieldset>
<legend>Account Details</legend>
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
<label for="password">Password</label>
<input type="password" id="password" name="password"
minlength="8" required
autocomplete="new-password">
<label for="confirm-password">Confirm Password</label>
<input type="password" id="confirm-password" name="confirm_password"
minlength="8" required>
</fieldset>
<button type="submit">Create Account</button>
</form>
<form action="/contact" method="POST" novalidate>
<h2>Contact Us</h2>
<fieldset>
<legend>Your Details</legend>
<div class="form-group">
<label for="contact-name">Full Name *</label>
<input type="text" id="contact-name" name="name"
placeholder="Rahul Sharma"
required minlength="2" maxlength="100"
autocomplete="name">
</div>
<div class="form-group">
<label for="contact-email">Email Address *</label>
<input type="email" id="contact-email" name="email"
placeholder="rahul@example.com"
required
autocomplete="email">
</div>
<div class="form-group">
<label for="contact-phone">Phone Number</label>
<input type="tel" id="contact-phone" name="phone"
placeholder="+91 98765 43210"
pattern="[+]?[0-9\s\-]{10,15}">
</div>
</fieldset>
<fieldset>
<legend>Your Message</legend>
<div class="form-group">
<label for="subject">Subject *</label>
<select id="subject" name="subject" required>
<option value="">— Select subject —</option>
<option value="general">General Inquiry</option>
<option value="support">Technical Support</option>
<option value="billing">Billing Question</option>
<option value="feedback">Feedback</option>
</select>
</div>
<div class="form-group">
<label for="message">Message *</label>
<textarea id="message" name="message"
rows="6"
placeholder="Describe your question or feedback..."
required minlength="20" maxlength="2000"></textarea>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="newsletter" value="yes">
Subscribe to WoHoTech newsletter
</label>
</div>
</fieldset>
<button type="submit">Send Message</button>
<button type="reset">Clear Form</button>
</form>
Summary
| Element | Purpose |
|---|
<form> | Form container — defines action and method |
<input> | Input field — varies by type attribute |
<label> | Label for an input — required for accessibility |
<textarea> | Multi-line text input |
<select> | Dropdown list |
<option> | Individual option in select or datalist |
<optgroup> | Groups options in select |
<fieldset> | Groups related form controls |
<legend> | Caption for a fieldset |
<button> | Clickable button (submit, reset, or generic) |
<datalist> | Autocomplete suggestions for an input |
*Next: Semantic HTML5 Elements*