2.6: Forms & Input Elements
Build interactive forms with input elements, validation, and proper labeling for accessibility. Learn form structure, input types, and how to handle user data submission.
1. Basic Form Structure
The <form> Element
<form action="/submit" method="POST">
<label for="username">Username:</label>
<input type="text" id="username" name="username">
<button type="submit">Submit</button>
</form>
Form attributes:
action- URL where form data is sentmethod- HTTP method (GETorPOST)enctype- Encoding type (for file uploads:multipart/form-data)autocomplete- Enable/disable browser autocompletenovalidate- Disable browser validation
GET vs POST
GET method:
<form action="/search" method="GET">
<input type="text" name="q" placeholder="Search...">
<button type="submit">Search</button>
</form>
Result: https://example.com/search?q=html+forms
When to use GET:
- Search forms
- Filters and sorting
- Bookmarkable URLs
- Read-only operations
POST method:
<form action="/login" method="POST">
<input type="email" name="email">
<input type="password" name="password">
<button type="submit">Log In</button>
</form>
Result: Data sent in request body (not visible in URL)
When to use POST:
- Sensitive data (passwords, personal info)
- Large amounts of data
- File uploads
- Data modification (create, update, delete)
2. Labels and Accessibility
The <label> Element
Two ways to associate labels with inputs:
Method 1: for attribute (recommended)
<label for="email">Email Address:</label>
<input type="email" id="email" name="email">
Method 2: Wrapping (implicit)
<label>
Email Address:
<input type="email" name="email">
</label>
Benefits of labels:
- Clicking label focuses input (larger click target)
- Screen readers announce label
- Better accessibility
- Required for good UX
Always Use Labels
<input type="text" placeholder="Enter your name">
<label for="name">Name:</label>
<input type="text" id="name" name="name" placeholder="Enter your name">
3. Text Input Types
Text Input
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
Email Input
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
Benefits:
- Mobile keyboards show @ key
- Built-in validation (checks for @ symbol)
Password Input
<label for="password">Password:</label>
<input type="password" id="password" name="password" required minlength="8">
Displays: •••••••• (hidden characters)
URL Input
<label for="website">Website:</label>
<input type="url" id="website" name="website" placeholder="https://example.com">
Benefits:
- Validates URL format
- Mobile keyboards optimized for URLs
Tel (Telephone) Input
<label for="phone">Phone:</label>
<input type="tel" id="phone" name="phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}">
Benefits:
- Mobile keyboards show number pad
- Can use
patternfor specific formats
Search Input
<label for="search">Search:</label>
<input type="search" id="search" name="q" placeholder="Search...">
Benefits:
- Shows clear (×) button in some browsers
- Semantic meaning for search
4. Number and Range Inputs
Number Input
<label for="quantity">Quantity:</label>
<input type="number" id="quantity" name="quantity" min="1" max="100" step="1" value="1">
Attributes:
min- Minimum valuemax- Maximum valuestep- Increment (default: 1)value- Default value
Example: Price
<label for="price">Price:</label>
<input type="number" id="price" name="price" min="0" step="0.01" placeholder="0.00">
Range (Slider) Input
<label for="volume">Volume:</label>
<input type="range" id="volume" name="volume" min="0" max="100" value="50">
<output for="volume">50</output>
<script>
const volumeSlider = document.getElementById('volume')
const volumeOutput = document.querySelector('output[for="volume"]')
volumeSlider.addEventListener('input', (e) => {
volumeOutput.textContent = e.target.value
})
</script>
Displays: Slider control (visual)
5. Date and Time Inputs
Date Input
<label for="birthdate">Birth Date:</label>
<input type="date" id="birthdate" name="birthdate" min="1900-01-01" max="2024-12-31">
Value format: YYYY-MM-DD
Time Input
<label for="appointment">Appointment Time:</label>
<input type="time" id="appointment" name="appointment" min="09:00" max="17:00" step="900">
Value format: HH:MM (24-hour)
step="900" = 15-minute intervals (900 seconds)
Datetime-local Input
<label for="meeting">Meeting Date & Time:</label>
<input type="datetime-local" id="meeting" name="meeting">
Value format: YYYY-MM-DDTHH:MM
Month Input
<label for="exp-month">Expiry Month:</label>
<input type="month" id="exp-month" name="exp_month">
Value format: YYYY-MM
Week Input
<label for="week">Select Week:</label>
<input type="week" id="week" name="week">
Value format: YYYY-W## (e.g., 2024-W42)
6. Choice Inputs
Checkbox (Multiple Selection)
<fieldset>
<legend>Select your interests:</legend>
<label>
<input type="checkbox" name="interests" value="coding" checked>
Coding
</label>
<label>
<input type="checkbox" name="interests" value="design">
Design
</label>
<label>
<input type="checkbox" name="interests" value="marketing">
Marketing
</label>
</fieldset>
Attributes:
checked- Pre-select checkboxvalue- Value sent to servername- Same name for related checkboxes
Radio Buttons (Single Selection)
<fieldset>
<legend>Select your experience level:</legend>
<label>
<input type="radio" name="level" value="beginner" checked>
Beginner
</label>
<label>
<input type="radio" name="level" value="intermediate">
Intermediate
</label>
<label>
<input type="radio" name="level" value="advanced">
Advanced
</label>
</fieldset>
Key difference from checkbox:
- Same
nameattribute groups radio buttons - Only one can be selected at a time
Select Dropdown
<label for="country">Country:</label>
<select id="country" name="country" required>
<option value="">-- Select Country --</option>
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="ca">Canada</option>
<option value="au">Australia</option>
</select>
With optgroups:
<label for="car">Choose a car:</label>
<select id="car" name="car">
<optgroup label="German Cars">
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
<option value="bmw">BMW</option>
</optgroup>
<optgroup label="Japanese Cars">
<option value="toyota">Toyota</option>
<option value="honda">Honda</option>
<option value="nissan">Nissan</option>
</optgroup>
</select>
Multiple selection:
<label for="languages">Languages you know:</label>
<select id="languages" name="languages" multiple size="5">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
<option value="python">Python</option>
<option value="java">Java</option>
</select>
7. Text Area
Multi-line text input:
<label for="message">Message:</label>
<textarea
id="message"
name="message"
rows="5"
cols="50"
maxlength="500"
placeholder="Enter your message here..."
required
></textarea>
<p><span id="char-count">0</span> / 500 characters</p>
<script>
const textarea = document.getElementById('message')
const charCount = document.getElementById('char-count')
textarea.addEventListener('input', (e) => {
charCount.textContent = e.target.value.length
})
</script>
Attributes:
rows- Visible rows (height)cols- Visible columns (width)maxlength- Maximum character countplaceholder- Placeholder text
Note: Don't put spaces between opening and closing tags:
<textarea>
Default text
</textarea>
<textarea>Default text</textarea>
8. File Upload
<label for="avatar">Choose profile picture:</label>
<input type="file" id="avatar" name="avatar" accept="image/png, image/jpeg">
Multiple files:
<label for="documents">Upload documents:</label>
<input type="file" id="documents" name="documents" multiple accept=".pdf,.doc,.docx">
Attributes:
accept- Allowed file types (MIME types or extensions)multiple- Allow multiple filescapture- Use device camera (mobile):capture="user"(front) orcapture="environment"(back)
Important: Form must have enctype="multipart/form-data" for file uploads:
<form action="/upload" method="POST" enctype="multipart/form-data">
<label for="file">Choose file:</label>
<input type="file" id="file" name="file">
<button type="submit">Upload</button>
</form>
9. Other Input Types
Color Picker
<label for="color">Choose color:</label>
<input type="color" id="color" name="color" value="#ff0000">
Displays: Native color picker
Hidden Input
<input type="hidden" name="user_id" value="12345">
Use cases:
- Passing data without displaying it
- CSRF tokens
- Session IDs
10. Fieldsets and Legends
Group related form fields:
<form>
<fieldset>
<legend>Personal Information</legend>
<label for="fname">First Name:</label>
<input type="text" id="fname" name="fname" required>
<label for="lname">Last Name:</label>
<input type="text" id="lname" name="lname" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</fieldset>
<fieldset>
<legend>Shipping Address</legend>
<label for="street">Street:</label>
<input type="text" id="street" name="street" required>
<label for="city">City:</label>
<input type="text" id="city" name="city" required>
<label for="zip">ZIP Code:</label>
<input type="text" id="zip" name="zip" required>
</fieldset>
<button type="submit">Submit</button>
</form>
Benefits:
- Visual grouping (border around fields)
- Semantic structure
- Screen readers announce group name
- Can disable entire fieldset:
<fieldset disabled>
11. Form Validation
Required Fields
<input type="text" name="username" required>
<input type="email" name="email" required>
Browser displays error if empty on submit
Pattern Validation (Regular Expressions)
<input
type="tel"
name="phone"
pattern="\([0-9]{3}\) [0-9]{3}-[0-9]{4}"
placeholder="(123) 456-7890"
required
>
<input
type="text"
name="username"
pattern="[a-zA-Z0-9]{3,16}"
title="Username must be 3-16 alphanumeric characters"
required
>
<input
type="text"
name="zip"
pattern="[0-9]{5}"
placeholder="12345"
required
>
title attribute: Displays validation message
Min/Max Length
<input type="password" name="password" minlength="8" maxlength="20" required>
<textarea name="bio" minlength="50" maxlength="500"></textarea>
Min/Max Values (Numbers, Dates)
<input type="number" name="age" min="18" max="120" required>
<input type="date" name="start_date" min="2024-01-01" max="2024-12-31">
Custom Validation Messages
<input
type="email"
id="email"
name="email"
required
oninvalid="this.setCustomValidity('Please enter a valid email address')"
oninput="this.setCustomValidity('')"
>
Disable Validation
<form novalidate>
</form>
<button type="submit" formnovalidate>Save Draft</button>
12. Button Types
Submit Button
<button type="submit">Submit Form</button>
<input type="submit" value="Submit Form">
Reset Button
<button type="reset">Clear Form</button>
Clears all form fields to default values
Regular Button (No Default Action)
<button type="button" onclick="doSomething()">Click Me</button>
Use for JavaScript actions without form submission
Image Button
<input type="image" src="submit-button.png" alt="Submit">
Acts as submit button with custom image
13. Form Styling
Basic Form Layout
<form class="contact-form">
<div class="form-group">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="message">Message:</label>
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<button type="submit">Send Message</button>
</form>
<style>
.contact-form {
max-width: 600px;
margin: 2rem auto;
padding: 2rem;
background: #f9f9f9;
border-radius: 8px;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
font-weight: bold;
color: #333;
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 1rem;
font-family: inherit;
}
.form-group input:focus,
.form-group textarea:focus {
outline: none;
border-color: #0066cc;
box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);
}
.contact-form button {
width: 100%;
padding: 1rem;
background: #0066cc;
color: white;
border: none;
border-radius: 4px;
font-size: 1rem;
font-weight: bold;
cursor: pointer;
transition: background 0.2s;
}
.contact-form button:hover {
background: #0052a3;
}
.contact-form button:active {
transform: translateY(1px);
}
</style>
Validation Styling
CSS pseudo-classes for form validation: Use :invalid selector for invalid inputs with red border, :valid selector for valid inputs with green border. Combine with :not(:placeholder-shown) to show validation only after user interaction. Use :focus state for active input styling with colored outlines.
Inline Form (Horizontal)
<form class="search-form">
<input type="search" name="q" placeholder="Search..." required>
<button type="submit">Search</button>
</form>
<style>
.search-form {
display: flex;
gap: 0.5rem;
max-width: 500px;
}
.search-form input {
flex: 1;
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 4px;
}
.search-form button {
padding: 0.75rem 1.5rem;
background: #0066cc;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
14. Complete Form Examples
Registration Form
<form class="registration-form" action="/register" method="POST">
<h2>Create Account</h2>
<fieldset>
<legend>Personal Information</legend>
<div class="form-group">
<label for="reg-fname">First Name:</label>
<input type="text" id="reg-fname" name="first_name" required>
</div>
<div class="form-group">
<label for="reg-email">Email:</label>
<input type="email" id="reg-email" name="email" required>
</div>
</fieldset>
<fieldset>
<legend>Account Security</legend>
<div class="form-group">
<label for="reg-username">Username:</label>
<input type="text" id="reg-username" name="username"
pattern="[a-zA-Z0-9_]{3,16}" required>
</div>
<div class="form-group">
<label for="reg-password">Password:</label>
<input type="password" id="reg-password" name="password"
minlength="8" required>
</div>
</fieldset>
<fieldset>
<legend>Preferences</legend>
<label><input type="checkbox" name="interests" value="web"> Web Development</label>
<label><input type="checkbox" name="interests" value="mobile"> Mobile Apps</label>
<label><input type="checkbox" name="newsletter" value="1"> Subscribe to newsletter</label>
</fieldset>
<div class="form-group">
<label>
<input type="checkbox" name="terms" required>
I accept the Terms and Conditions
</label>
</div>
<button type="submit">Create Account</button>
</form>
Survey Form
<form class="survey-form" action="/survey" method="POST">
<h2>Customer Satisfaction Survey</h2>
<div class="form-group">
<label for="customer-name">Name:</label>
<input type="text" id="customer-name" name="name" required>
</div>
<fieldset>
<legend>How satisfied are you with our service?</legend>
<label><input type="radio" name="satisfaction" value="5" required> Very Satisfied</label>
<label><input type="radio" name="satisfaction" value="3"> Neutral</label>
<label><input type="radio" name="satisfaction" value="1"> Very Dissatisfied</label>
</fieldset>
<div class="form-group">
<label for="visit-frequency">How often do you use our service?</label>
<select id="visit-frequency" name="frequency" required>
<option value="">-- Select --</option>
<option value="daily">Daily</option>
<option value="monthly">Monthly</option>
</select>
</div>
<div class="form-group">
<label for="comments">Additional Comments:</label>
<textarea id="comments" name="comments" rows="5"></textarea>
</div>
<button type="submit">Submit Survey</button>
</form>
15. Practical Exercises
Exercise 2.6.1: Contact Form
Create a contact form with:
- Name (text, required)
- Email (email, required)
- Subject (select dropdown with 5 options)
- Message (textarea, required, 500 char max)
- Submit button
- Proper labels and styling
Exercise 2.6.2: Login Form
Build a login form with:
- Email input with validation
- Password input (min 8 characters)
- "Remember me" checkbox
- Submit button
- "Forgot password?" link
- Responsive styling
Exercise 2.6.3: Job Application Form
Create a comprehensive job application with:
- Personal info fieldset (name, email, phone)
- Experience level (radio buttons)
- Skills (multiple checkboxes)
- Resume upload (file input, PDF only)
- Cover letter (textarea)
- All fields with proper validation
- Professional styling
Exercise 2.6.4: Booking Form
Build a hotel booking form with:
- Check-in date (date input, min: today)
- Check-out date (date input)
- Number of guests (number input, 1-10)
- Room type (select dropdown)
- Special requests (textarea, optional)
- Total price calculator (JavaScript)
- Validation ensuring check-out > check-in
16. Knowledge Check
Question 1: What's the difference between GET and POST methods?
Show answer
GET appends data to URL (visible, bookmarkable, for searches/filters). POST sends data in request body (hidden, for sensitive data, large payloads, and data modification).Question 2: Why is the <label> element important?
Show answer
Labels improve accessibility (screen readers announce them), increase click target (clicking label focuses input), and are required for good UX. Always associate labels with inputs using `for` attribute.Question 3: How do you group related form fields?
Show answer
Use `Question 4: What's the difference between radio buttons and checkboxes?
Show answer
Radio buttons allow only ONE selection from a group (same `name` attribute). Checkboxes allow MULTIPLE selections. Use radio for exclusive choices, checkboxes for multiple choices.Question 5: How do you validate an email input?
Show answer
Use `type="email"` for built-in validation. Add `required` for mandatory field. Can also use `pattern` attribute for custom validation regex if needed.Question 6: What's required for file upload forms?
Show answer
1) ``, 2) Form must use `method="POST"`, 3) Form must have `enctype="multipart/form-data"`. Use `accept` attribute to limit file types.17. Common Mistakes
Missing Labels
<input type="text" placeholder="Name">
<label for="name">Name:</label>
<input type="text" id="name" name="name">
Wrong Input Type
<input type="text" name="email">
<input type="email" name="email" required>
No Name Attribute
<input type="text" id="username">
<input type="text" id="username" name="username">
Using Placeholder as Label
<input type="text" placeholder="Enter your name">
<label for="name">Name:</label>
<input type="text" id="name" name="name" placeholder="John Doe">
18. Key Takeaways
- Always use
<label>elements - Required for accessibility - Use appropriate input types -
email,tel,number,date, etc. - Include
nameattribute - Required for form submission - Use GET for searches, POST for data - Choose method based on use case
- Group with
<fieldset>and<legend>- Better structure and accessibility - Validate with HTML5 attributes -
required,pattern,min/max - Radio buttons for single choice - Checkboxes for multiple
- File uploads need
enctype-multipart/form-data - Style focus states clearly - Important for keyboard navigation
- Test with keyboard only - Ensure tab order and accessibility
19. Further Resources
Official Documentation:
Accessibility:
Validation:
- HTML5 Pattern - Common regex patterns
- Form Validation UX
Next Steps
Excellent work! You now know how to build accessible, validated HTML forms.
In Lesson 2.7: Semantic HTML5, you'll learn the final piece of Phase 2 - using semantic HTML elements for better structure, accessibility, and SEO.