beginner22 min

Forms, Validation & Accessibility Foundations

Build usable forms with properly linked labels, built-in browser validation, and the accessibility basics every page needs.

What you'll learn

  • Build a form using <form>, <label>, <input>, <select>, and <textarea>
  • Associate every input with a label via matching id/for attributes
  • Use HTML validation attributes like required and type to catch bad input before it's submitted
  • Apply core accessibility practices, including landmark elements and meaningful alt text

Prerequisites

Explanation

Forms are how the web collects information from people — signing up, searching, checking out. A form that "looks fine" visually can still be nearly unusable for someone using a screen reader or only a keyboard, which is why labels and structure matter just as much as the input boxes themselves.

The Building Blocks

A <form> element wraps a group of related controls. Inside it, you'll typically reach for:

  • <input> — a single-line control whose behavior changes entirely based on its type attribute: text, email, password, checkbox, radio, number, and more. Browsers apply different keyboards on mobile and different built-in validation depending on the type.
  • <textarea> — a multi-line text box, for longer input like a message or comment.
  • <select> with nested <option> elements — a dropdown list of choices.
  • <button> — commonly type="submit" to send the form.

Labels Are Not Optional

Every input needs an associated <label>. The reliable way to connect them is matching attributes: give the input an id, and give the label a for attribute with that same value, e.g. <label for="email">Email</label> paired with <input id="email" ...>. This connection does two concrete things: a screen reader announces the label's text when the input receives focus, and clicking the label text itself moves focus into the input — genuinely helpful for small checkboxes and radio buttons that are otherwise fiddly to click precisely.

A placeholder is not a substitute for a label. Placeholder text disappears the moment someone starts typing, isn't reliably announced the same way a label is, and often has poor contrast — it's a hint, not a name for the field.

Built-in Validation

Long before you write a single line of JavaScript, HTML itself can catch obviously invalid input:

  • required prevents submission if the field is left empty.
  • type="email" checks for a basic email shape.
  • minlength / maxlength constrain text length.
  • pattern accepts a custom regular expression for more specific formats.

These attributes don't replace server-side validation (never trust data from a browser alone), but they give people immediate, helpful feedback without a network round trip.

Accessibility Foundations

Three habits go a long way toward an accessible page:

  1. Use landmark elements (from the previous lesson) — header, nav, main, footer — so assistive technology users can jump directly to the section they need.
  2. Give every meaningful image real alt text, and use alt="" explicitly for purely decorative images so screen readers skip them cleanly.
  3. Label everything interactive — not just form inputs, but also icon-only buttons, which need something like aria-label="Close" when there's no visible text at all.

Accessibility isn't a separate feature you bolt on afterward — it's mostly just finishing the HTML properly: real labels, real alt text, and real semantic structure, all of which you were already halfway toward by using the right elements in the first place.

Example

A labeled contact form with validation attributes, wrapped in semantic landmarks.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Contact us</title>
  </head>
  <body>
    <main>
      <h1>Contact us</h1>
      <form>
        <fieldset>
          <legend>Your details</legend>
          <div>
            <label for="name">Name</label>
            <input type="text" id="name" name="name" required minlength="2" />
          </div>
          <div>
            <label for="email">Email</label>
            <input type="email" id="email" name="email" required />
          </div>
          <div>
            <label for="topic">Topic</label>
            <select id="topic" name="topic">
              <option value="support">Support</option>
              <option value="sales">Sales</option>
            </select>
          </div>
          <div>
            <label for="message">Message</label>
            <textarea id="message" name="message" rows="4"></textarea>
          </div>
        </fieldset>
        <button type="submit">Send</button>
      </form>
    </main>
  </body>
</html>

Try it yourself

Add a 'Phone' field with its own <label> and <input>, correctly linked by id/for, then press Run.

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Guided exercise

Guided exercise

Add a <label for="email">Email</label> correctly linked to the existing email input, and make that email input required.

Checks: A <label for="email"> exists · The email input has the required attribute · plus 1 hidden check

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Independent exercise

Independent exercise

Build a signup form with: a required text input for username, a required password input, and a <select> with at least two <option> choices for country. Every input and select must have its own correctly linked <label>.

Checks: Includes a <form> · Every input/select has a matching label · Username input is required · Password input exists and is required · plus 1 hidden check

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Common mistakes

  • Using placeholder text instead of a real <label>, which disappears once typing starts and isn't reliably read by screen readers.
  • Giving an input an id that doesn't exactly match its label's for attribute, silently breaking the label/input connection.
  • Relying only on required and type validation for security — client-side validation helps usability, but the server must always re-validate.
  • Building icon-only buttons with no visible text and no aria-label, leaving screen reader users with no idea what the button does.

Knowledge check

Knowledge check

1. What correctly connects a <label> to an <input>?
2. Why shouldn't placeholder text replace a <label>?
3. What does the required attribute do on an <input>?
4. Why might an icon-only button need an aria-label?

Takeaway

A form is only as good as its labels — get the id/for connection right on every field, and validation attributes and accessibility both come along almost for free.

Summary

Forms combine input, textarea, select, and button elements inside a <form>, but every control needs a correctly linked <label> to be genuinely usable. Built-in attributes like required, type, and minlength catch obvious mistakes before submission, and combining that with semantic landmarks and meaningful alt text covers the accessibility foundations every page needs.

References

Your notes

Notes save automatically.

Finished this lesson?

Mark it complete to track your progress and schedule a future review.