# Inputs, Labels, and Why `<label>` Matters

Start the signup form: name, email, password, and a checkbox agreeing to terms. The markup looks
trivial, but each piece carries weight most people skip past.

## Input types are not interchangeable

Every `<input>` has a `type`, and the type changes more than validation - it changes the keyboard a
phone shows, the browser's built-in checks, and how the value gets stored.

```html
<input type="text" name="fullName">
<input type="email" name="email">
<input type="password" name="password">
<input type="checkbox" name="agree">
```

- **`text`** - a plain string. No format checking, no special keyboard.
- **`email`** - mobile browsers show an `@` key; desktop browsers reject submission if the value has
  no `@` and domain shape, even before you write a line of JavaScript.
- **`password`** - masks the characters as dots and tells password managers this field is sensitive.
- **`checkbox`** - a boolean. Checked or not; there's no "value" the user types.

There's also `radio` for picking one option from a set:

```html
<input type="radio" name="plan" value="free" id="plan-free">
<label for="plan-free">Free</label>
<input type="radio" name="plan" value="pro" id="plan-pro">
<label for="plan-pro">Pro</label>
```

Radio buttons only work as a group when they share the same `name` - that's how the browser knows
they're mutually exclusive. Give each one a different `value` so you know which was picked.

📝 **Terminology.** `type="email"` doesn't guarantee a *real, deliverable* email address - it only
checks the address is shaped like one (`something@something.something`). Confirming the address exists
still needs a verification email.

## `<label>` is not decoration

A `<label>` wrapped around text next to an input looks the same with or without the `for` attribute.
The difference only shows up when someone interacts with the page differently than you did while
building it.

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

The `for` attribute must match the input's `id`. That connection does two concrete things:

1. **Bigger click target.** Clicking the label text "Email" focuses the input - not just clicking the
   box itself. For checkboxes and radio buttons this matters even more: the label turns a tiny 16px
   square into a click target the width of the whole sentence.
2. **Screen reader association.** Without `for`/`id`, a screen reader announces "edit text, blank." With
   it, the reader announces "Email, edit text, blank" - the user knows what they're filling in before
   they start typing. This is table stakes, not a nice-to-have; the full accessibility treatment for
   forms and beyond is in [Accessibility From Day One](/guides/accessibility-from-day-one).

⚠️ **Gotcha.** A `placeholder` is not a label. Placeholder text disappears the moment someone starts
typing, has no association a screen reader relies on, and often fails color-contrast checks because
it's styled light gray by default. Use `placeholder` for a format hint ("MM/DD/YYYY") alongside a real
`<label>`, never as a replacement for one.

You can skip `for`/`id` by wrapping the input inside the label instead:

```html
<label>
  Email
  <input type="email" name="email">
</label>
```

This works and is valid HTML, but it's harder to style precisely (the input inherits label layout
quirks) and harder to scan in longer forms. Prefer explicit `for`/`id` pairs once a form has more than
one or two fields.

## Grouping related inputs with `<fieldset>`

The "I agree to terms" checkbox is one field, but the moment a form has more than one option that
belongs together - a set of radio buttons, several checkboxes for notification preferences - group them
with `<fieldset>` and describe the group with `<legend>`:

```html
<fieldset>
  <legend>Notify me about</legend>
  <label for="notify-news"><input type="checkbox" id="notify-news" name="notify" value="news"> Product news</label>
  <label for="notify-tips"><input type="checkbox" id="notify-tips" name="notify" value="tips"> Tips</label>
</fieldset>
```

A screen reader announces the legend before each field inside the fieldset, so "Product news" is heard
as "Notify me about, Product news" - the group's purpose travels with every item in it. Visually,
browsers render a `<fieldset>` with a border and the `<legend>` sitting on top of it by default; override
that with CSS if it doesn't fit your design, but keep the elements themselves.

## The signup form so far

```html
<form>
  <div>
    <label for="fullName">Full name</label>
    <input type="text" id="fullName" name="fullName" required>
  </div>

  <div>
    <label for="email">Email</label>
    <input type="email" id="email" name="email" required>
  </div>

  <div>
    <label for="password">Password</label>
    <input type="password" id="password" name="password" required>
  </div>

  <fieldset>
    <legend>Terms</legend>
    <label for="agree">
      <input type="checkbox" id="agree" name="agree" required>
      I agree to the terms of service
    </label>
  </fieldset>

  <button type="submit">Create account</button>
</form>
```

Every input has a matching label. The checkbox lives inside its own label so clicking the sentence
toggles it. Next phase turns those stray `required` attributes into a real validation strategy.

Check what you just covered:

```quiz
[
  {
    "q": "What does `<label for=\"email\">` connect to?",
    "choices": ["The form's action URL", "An input with a matching id", "The page's title"],
    "answer": 1,
    "explain": "The for attribute must match the input's id - that pairing is what makes the label clickable and screen-reader-associated."
  },
  {
    "q": "Why shouldn't a placeholder replace a label?",
    "choices": ["Placeholders are deprecated", "Placeholder text disappears on typing and isn't reliably read by screen readers", "Placeholders only work on checkboxes"],
    "answer": 1,
    "explain": "Once the user types, the placeholder is gone - and it was never announced as a real label to begin with."
  },
  {
    "q": "What makes a group of radio buttons mutually exclusive?",
    "choices": ["Wrapping them in a <fieldset>", "Giving them the same name attribute", "Giving them the same id"],
    "answer": 1,
    "explain": "Radio buttons only exclude each other within a shared name group. id must stay unique per element."
  }
]
```
