Forms collect user input and send it to a server. They're essential for login pages, search bars, contact forms, and more.
Basic Form Structure
HTML
<form action="/submit" method="POST">
<!-- action = where to send data -->
<!-- method = HTTP method (GET or POST) -->
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<button type="submit">Submit</button>
</form>GET vs POST
| GET | POST | |
|---|---|---|
| Data in URL | ✅ Yes (?key=value) | ❌ No (in body) |
| Visible in address bar | ✅ Yes | ❌ No |
| Use case | Search, filtering | Login, uploads, forms |
| Security | Less secure | More secure |
| Bookmarkable | ✅ Yes | ❌ No |
| Data limit | ~2000 chars | No limit |
HTML
<!-- GET: data appears in URL -->
<form action="/search" method="GET">
<input type="text" name="q" placeholder="Search...">
<button type="submit">Search</button>
</form>
<!-- URL: /search?q=hello -->
<!-- POST: data sent in body (hidden from URL) -->
<form action="/login" method="POST">
<input type="email" name="email">
<input type="password" name="password">
<button type="submit">Login</button>
</form>Input Types
HTML
<!-- Text inputs -->
<input type="text" name="name" placeholder="Your name">
<input type="email" name="email" placeholder="you@example.com">
<input type="password" name="password" placeholder="Password">
<input type="search" name="q" placeholder="Search...">
<input type="url" name="website" placeholder="https://example.com">
<input type="tel" name="phone" placeholder="+1 234 567 890">
<input type="number" name="age" min="0" max="150" step="1">
<input type="range" name="volume" min="0" max="100">
<input type="color" name="color" value="#3b82f6">
<!-- Date/Time inputs -->
<input type="date" name="birthday">
<input type="time" name="meeting-time">
<input type="datetime-local" name="appointment">
<input type="month" name="start-month">
<input type="week" name="start-week">
<!-- File input -->
<input type="file" name="avatar" accept="image/*">
<input type="file" name="documents" multiple accept=".pdf,.doc">
<!-- Hidden input (not visible to user) -->
<input type="hidden" name="user-id" value="42">
<!-- Checkbox -->
<input type="checkbox" id="terms" name="terms" required>
<label for="terms">I agree to the Terms</label>
<!-- Radio buttons (same name = mutually exclusive) -->
<input type="radio" id="html" name="language" value="html" checked>
<label for="html">HTML</label>
<input type="radio" id="css" name="language" value="css">
<label for="css">CSS</label>
<input type="radio" id="js" name="language" value="js">
<label for="js">JavaScript</label>Labels — Always Use Them!
HTML
<!-- For attribute connects label to input (click on label focuses input) -->
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<!-- Wrapping (implicit association) -->
<label>
Email:
<input type="email" name="email">
</label>
<!-- Required field indicator -->
<label for="name">Name <span aria-label="required">*</span>:</label>
<input type="text" id="name" name="name" required>Form Elements
HTML
<!-- Textarea (multi-line text) -->
<label for="bio">Bio:</label>
<textarea id="bio" name="bio" rows="4" cols="50" maxlength="500"
placeholder="Tell us about yourself..."></textarea>
<!-- Select dropdown -->
<label for="country">Country:</label>
<select id="country" name="country">
<option value="">Select a country</option>
<optgroup label="North America">
<option value="us">United States</option>
<option value="ca">Canada</option>
</optgroup>
<optgroup label="Europe">
<option value="uk">United Kingdom</option>
<option value="fr">France</option>
<option value="de">Germany</option>
</optgroup>
</select>
<!-- Multiple select -->
<select name="skills" multiple size="4">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
<option value="python">Python</option>
</select>
<!-- Datalist (autocomplete suggestions) -->
<label for="browser">Browser:</label>
<input type="text" id="browser" name="browser" list="browsers">
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
<option value="Opera">
</datalist>
<!-- Button types -->
<button type="submit">Submit</button> <!-- Submits form -->
<button type="reset">Reset</button> <!-- Resets form -->
<button type="button">Click Me</button> <!-- No default action -->Fieldset and Legend
HTML
<form action="/register" method="POST">
<fieldset>
<legend>Personal Information</legend>
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</fieldset>
<fieldset>
<legend>Preferences</legend>
<label for="theme">Theme:</label>
<select id="theme" name="theme">
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
<label>
<input type="checkbox" name="newsletter" checked>
Subscribe to newsletter
</label>
</fieldset>
<button type="submit">Register</button>
</form>Input Attributes
HTML
<input type="text" name="name"
required <!-- Must be filled -->
readonly <!-- Can see but not edit -->
disabled <!-- Grayed out, not submitted -->
placeholder="Enter name" <!-- Hint text -->
maxlength="50" <!-- Max characters -->
minlength="2" <!-- Min characters -->
size="30" <!-- Visible width -->
value="Default" <!-- Default value -->
autofocus <!-- Auto-focus on page load -->
autocomplete="off" <!-- Disable autocomplete -->
>Form Validation
HTML
<!-- Built-in browser validation -->
<input type="email" required> <!-- Must be valid email -->
<input type="number" min="0" max="100"> <!-- Number in range -->
<input type="text" pattern="[A-Za-z]{3,}" title="At least 3 letters">
<input type="text" required minlength="3" maxlength="20">
<!-- Custom validation message -->
<input type="email" id="email" required>
<script>
document.getElementById('email').setCustomValidity(
'Please enter a valid email address'
);
</script>Knowledge Check
4 questions — test your understanding
1
What is the difference between GET and POST?
2
Why should you always use <label> elements?
3
What does the <fieldset> element do?
4
What does the multiple attribute do on <select>?
Next: HTML Semantic Elements