Web DevelopmentHTMLCSS

HTML Forms and Inputs: Build Your First Web Form

Learn how to build HTML forms from scratch. Covers input types, labels, textarea, select, checkboxes, radio buttons, form validation, and accessibility best practices.

TT
Emily Ross
5 min read
HTML Forms and Inputs: Build Your First Web Form

Forms are how users interact with the web — logging in, signing up, placing orders, sending messages. Every form you've ever filled in is built with HTML form elements. Getting them right matters for usability, accessibility, and the data quality you receive on the backend.

This lesson covers the complete set of form elements: input types, labels, validation, and the structure of a real-world form.


The <form> Element

Every form starts with the <form> element. It groups form controls and specifies where to send the data:

html
<form action="/submit" method="post">
  <!-- form fields go here -->
</form>

Key <form> Attributes

AttributePurposeValues
actionURL to send the form data toAny URL string
methodHTTP method used to submitget or post
enctypeEncoding type (required for file uploads)multipart/form-data
novalidateDisable browser's built-in validationBoolean

method="get" appends form data to the URL as query parameters — good for search forms. method="post" sends data in the request body, not visible in the URL — use for login, signup, and anything sensitive.


The <input> Element

<input> is the most versatile form element. The type attribute determines what kind of input it is.

Common Input Types

html
<!-- Single-line text -->
<input type="text" name="username" placeholder="Enter your username">

<!-- Email (validated format, email keyboard on mobile) -->
<input type="email" name="email" placeholder="you@example.com">

<!-- Password (masked characters) -->
<input type="password" name="password">

<!-- Number with constraints -->
<input type="number" name="age" min="18" max="120" step="1">

<!-- Checkbox (boolean toggle) -->
<input type="checkbox" name="newsletter" id="newsletter" value="yes">
<label for="newsletter">Subscribe to the newsletter</label>

<!-- File upload -->
<input type="file" name="resume" accept=".pdf,.doc,.docx">

<!-- Hidden value (submitted but not visible) -->
<input type="hidden" name="csrf_token" value="abc123xyz">

Full Input Type Reference

typePurpose
textSingle-line text
emailEmail address (validated)
passwordMasked password
numberNumeric value
telPhone number
urlWeb address (validated)
searchSearch query
checkboxBoolean toggle
radioSingle choice from group
rangeSlider for a numeric range
dateDate picker
timeTime picker
datetime-localDate + time picker
colorColour picker
fileFile upload
hiddenHidden value
submitForm submission button
resetResets form to defaults

Radio Buttons

Radio buttons let a user pick one option from a group. All radio buttons in a group share the same name attribute — this is what links them together:

html
<fieldset>
  <legend>Preferred contact method</legend>
  <input type="radio" name="contact" id="email-radio" value="email">
  <label for="email-radio">Email</label>

  <input type="radio" name="contact" id="phone-radio" value="phone">
  <label for="phone-radio">Phone</label>
</fieldset>

Submit Button

html
<button type="submit">Send Message</button>

<button> is preferred over <input type="submit"> — it can contain HTML (icons, formatted text) and is easier to style.


Labels: <label>

Every input needs a visible label. The <label> element links a text description to a form control:

html
<label for="email">Email address</label>
<input type="email" id="email" name="email">

The for attribute on <label> must match the id attribute on the input. When linked: clicking the label focuses the input (larger click target), screen readers announce the label when the input is focused, and the relationship is explicit in the accessibility tree.

Never skip labels. Placeholder text is not a substitute — it disappears when the user starts typing.


Multi-Line Text: <textarea>

html
<label for="message">Message</label>
<textarea id="message" name="message" rows="5" placeholder="Your message here..."></textarea>

Unlike <input>, <textarea> has an opening and closing tag. Default content goes between the tags (not in a value attribute). rows sets the default visible height, though CSS is the better way to control dimensions.


Dropdown Menus: <select>

html
<label for="country">Country</label>
<select id="country" name="country">
  <option value="">-- Select a country --</option>
  <option value="gb">United Kingdom</option>
  <option value="us">United States</option>
  <option value="ca">Canada</option>
</select>

Use <optgroup> to group related options under a label:

html
<select name="language">
  <optgroup label="Frontend">
    <option value="html">HTML</option>
    <option value="css">CSS</option>
  </optgroup>
  <optgroup label="Backend">
    <option value="python">Python</option>
  </optgroup>
</select>

Grouping: <fieldset> and <legend>

html
<fieldset>
  <legend>Billing Address</legend>

  <label for="street">Street</label>
  <input type="text" id="street" name="street">

  <label for="city">City</label>
  <input type="text" id="city" name="city">
</fieldset>

<fieldset> groups related form controls. <legend> provides a caption for the group. Screen readers announce the legend before each control inside the fieldset.


HTML Form Validation

Modern browsers can validate form inputs before submission using HTML attributes — no JavaScript required:

html
<input type="email" name="email" required>
<input type="text" name="username" required minlength="3" maxlength="20">
<input type="number" name="age" min="18" max="99" required>
<input type="url" name="website" pattern="https://.*">
AttributeEffect
requiredField must not be empty
minlengthMinimum number of characters
maxlengthMaximum number of characters
min / maxMinimum / maximum for number/date inputs
patternMust match a regular expression

A Complete Contact Form

html
<form action="/contact" method="post">
  <fieldset>
    <legend>Contact Us</legend>

    <label for="name">Full name</label>
    <input type="text" id="name" name="name" required minlength="2" placeholder="Jane Smith">

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

    <label for="subject">Subject</label>
    <select id="subject" name="subject" required>
      <option value="">-- Select a subject --</option>
      <option value="support">Technical Support</option>
      <option value="billing">Billing</option>
      <option value="general">General Enquiry</option>
    </select>

    <label for="message-field">Message</label>
    <textarea id="message-field" name="message" rows="6" required placeholder="Describe your issue or question..."></textarea>

    <label>
      <input type="checkbox" name="consent" required>
      I agree to the <a href="/privacy">privacy policy</a>
    </label>

    <button type="submit">Send Message</button>
  </fieldset>
</form>

Previous: Lesson 4 — HTML Lists & Tables | Next: Lesson 6 — CSS Fundamentals


Part of the HTML & CSS Fundamentals course.

External references: