HTML Forms

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>?