Advertisement
πŸ› οΈ Projects

HTML Registration Form Project – Complete Sign-Up Form

This project builds a complete, real-world user registration form using every major HTML input type, <fieldset>/<legend> for grouping, <label>/for for accessibility, and built-in HTML5 validation. By the end you will have a portfolio-ready form that demonstrates mastery of HTML forms.

⏱️ 20 min read🎯 BeginnerπŸ“… Updated 2026

What We Build

A sign-up form for a fictional learning platform with five logical sections:

  • Personal Details β€” first name, last name, date of birth, phone
  • Account Setup β€” email, password, confirm password
  • Address β€” street, city, postcode, country (select)
  • Preferences β€” interests (checkboxes), experience level (radio), newsletter (range)
  • Terms & Submit β€” avatar upload, terms checkbox, submit button

Section 1 – Personal Details

HTML
<form action="/register" method="POST" novalidate>

  <fieldset>
    <legend>Personal Details</legend>

    <label for="firstName">First Name</label>
    <input type="text" id="firstName" name="firstName"
           required minlength="2" maxlength="50"
           placeholder="Jane" autocomplete="given-name">

    <label for="lastName">Last Name</label>
    <input type="text" id="lastName" name="lastName"
           required minlength="2" maxlength="50"
           placeholder="Smith" autocomplete="family-name">

    <label for="dob">Date of Birth</label>
    <input type="date" id="dob" name="dob"
           required min="1900-01-01" max="2010-12-31">

    <label for="phone">Phone Number</label>
    <input type="tel" id="phone" name="phone"
           pattern="[\+]?[0-9\s\-\(\)]{7,20}"
           placeholder="+44 7700 900000" autocomplete="tel">
  </fieldset>

Section 2 – Account Setup

HTML
  <fieldset>
    <legend>Account Setup</legend>

    <label for="email">Email Address</label>
    <input type="email" id="email" name="email"
           required autocomplete="email"
           placeholder="jane@example.com">

    <label for="password">Password</label>
    <input type="password" id="password" name="password"
           required minlength="8"
           pattern="(?=.*[A-Z])(?=.*[0-9]).{8,}"
           autocomplete="new-password"
           placeholder="Min 8 chars, 1 uppercase, 1 number">

    <label for="confirmPassword">Confirm Password</label>
    <input type="password" id="confirmPassword" name="confirmPassword"
           required autocomplete="new-password"
           placeholder="Repeat password">
  </fieldset>
Advertisement

Section 3 – Address

HTML
  <fieldset>
    <legend>Address</legend>

    <label for="street">Street Address</label>
    <input type="text" id="street" name="street"
           placeholder="123 Main Street" autocomplete="street-address">

    <label for="city">City</label>
    <input type="text" id="city" name="city"
           placeholder="London" autocomplete="address-level2">

    <label for="postcode">Postcode</label>
    <input type="text" id="postcode" name="postcode"
           pattern="[A-Z]{1,2}[0-9][A-Z0-9]? ?[0-9][A-Z]{2}"
           placeholder="SW1A 1AA" autocomplete="postal-code">

    <label for="country">Country</label>
    <select id="country" name="country" required autocomplete="country-name">
      <option value="">-- Select country --</option>
      <optgroup label="Common">
        <option value="GB">United Kingdom</option>
        <option value="US">United States</option>
        <option value="CA">Canada</option>
        <option value="AU">Australia</option>
      </optgroup>
      <optgroup label="Europe">
        <option value="DE">Germany</option>
        <option value="FR">France</option>
        <option value="NL">Netherlands</option>
      </optgroup>
    </select>
  </fieldset>

Section 4 – Preferences

HTML
  <fieldset>
    <legend>Preferences</legend>

    <!-- Checkboxes: multiple interests -->
    <p>Topics of interest:</p>
    <label><input type="checkbox" name="interests" value="html"> HTML & CSS</label>
    <label><input type="checkbox" name="interests" value="js"> JavaScript</label>
    <label><input type="checkbox" name="interests" value="python"> Python</label>
    <label><input type="checkbox" name="interests" value="owl"> OWL JS / Odoo</label>

    <!-- Radio: experience level -->
    <p>Experience level:</p>
    <label><input type="radio" name="experience" value="beginner" required> Beginner</label>
    <label><input type="radio" name="experience" value="intermediate"> Intermediate</label>
    <label><input type="radio" name="experience" value="advanced"> Advanced</label>

    <!-- Range: how many hours per week -->
    <label for="hoursPerWeek">
      Hours per week you can study:
      <output id="hoursOutput">5</output>h
    </label>
    <input type="range" id="hoursPerWeek" name="hoursPerWeek"
           min="1" max="40" value="5" step="1"
           oninput="document.getElementById('hoursOutput').value = this.value">

    <!-- Select: account type -->
    <label for="accountType">Account type:</label>
    <select id="accountType" name="accountType">
      <option value="individual">Individual</option>
      <option value="student">Student</option>
      <option value="business">Business / Team</option>
    </select>
  </fieldset>

Section 5 – Terms & Submit

HTML
  <fieldset>
    <legend>Final Steps</legend>

    <!-- File upload: avatar -->
    <label for="avatar">Profile photo (optional)</label>
    <input type="file" id="avatar" name="avatar"
           accept="image/png, image/jpeg, image/webp">

    <!-- Terms checkbox -->
    <label>
      <input type="checkbox" name="terms" required>
      I agree to the
      <a href="/terms.html" target="_blank" rel="noopener noreferrer">Terms of Service</a>
      and
      <a href="/privacy-policy.html" target="_blank" rel="noopener noreferrer">Privacy Policy</a>
    </label>

    <!-- Newsletter opt-in -->
    <label>
      <input type="checkbox" name="newsletter" value="yes">
      Send me tips and updates by email
    </label>

    <!-- Hidden field for tracking -->
    <input type="hidden" name="source" value="homepage-signup">

    <button type="submit">Create My Account</button>
    <button type="reset">Clear Form</button>
  </fieldset>

</form>

Accessibility Notes

Feature usedWhy it matters
<label for="id">Links label to input β€” screen readers announce label when input is focused
<fieldset> + <legend>Groups related fields β€” screen readers announce legend before each field in the group
autocompleteBrowsers autofill from user's saved data β€” faster form completion, especially on mobile
requiredBrowser validates before submit β€” communicates mandatory fields
patternCustom format validation with regex
placeholderShows expected format β€” never a replacement for a label
⚠️
Always validate on the server too

HTML5 validation (required, pattern, type) can be bypassed by disabling JavaScript or sending raw HTTP requests. Always re-validate all form data on the server side before saving to a database or acting on it.

πŸ‹οΈ Practical Exercise

  1. Build a form with name, email, and password fields.
  2. Associate a <label> with each input.
  3. Make all fields required.
  4. Add a password field with a minlength.
  5. Add a submit button and a "terms" checkbox.

πŸ”₯ Challenge Exercise

Build an accessible registration form: grouped <fieldset>s, labeled inputs, built-in validation (required, email type, password pattern), and a required terms checkbox. Submit invalid data to trigger browser validation. Explain why both client-side and server-side validation are needed.

πŸ“‹ Summary

  • Group related fields with <fieldset> + <legend> for structure and accessibility.
  • Every input must have a matching <label for="id">.
  • Use appropriate type for each field: email, password, date, tel, file, etc.
  • Add autocomplete attributes β€” speeds up form completion on mobile.
  • Use required, minlength, pattern for client-side validation β€” always validate server-side too.
  • type="hidden" passes data the user doesn't see (tracking source, CSRF tokens).

Interview Questions

  • What fields does a typical registration form include?
  • How do you make form fields accessible with labels?
  • What built-in validation can a registration form use?
  • How would you validate that two password fields match?
  • Why is server-side validation still required?

FAQ

Can HTML alone check that two passwords match? +

Not directly β€” HTML has no "equals another field" rule. You compare the two values with a little JavaScript, or validate on the server. HTML handles required, length, pattern, and type checks.

Is HTML form validation secure? +

No. It improves UX by catching mistakes early, but users can bypass it (disable JS, edit the page, or post directly). Always re-validate on the server.