# Labels Everywhere

**MUST** · **ID:** `forms-labels-everywhere` · **Category:** forms
**Source:** [Vercel](https://github.com/vercel-labs/agent-skills/blob/main/skills/web-design-guidelines/SKILL.md)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/forms-labels-everywhere

> MUST: Every control has a <label> or is associated with a label for assistive tech

Every form control must have a visible label or accessible name

Labels are crucial for accessibility. Screen reader users need labels to understand what each form field is for. Sighted users benefit from clear labels too. Use the <label> element with the "for" attribute pointing to the input's id, or wrap the input inside the label.

## Bad — do not do this

`forms-labels-everywhere-bad`

```tsx
import { ScreenReaderView } from '@/components/demo-kit/ScreenReaderView';

export function LabelsEverywhereBad() {
  return (
    <div className="w-full max-w-sm space-y-4">
      <ScreenReaderView>
        <div className="space-y-4">
          <input
            type="text"
            className="w-full px-3 py-2 border border-border rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
            placeholder="Full Name"
          />
          <input
            type="email"
            className="w-full px-3 py-2 border border-border rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
            placeholder="Email"
          />
          <input
            type="tel"
            className="w-full px-3 py-2 border border-border rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
            placeholder="Phone"
          />
        </div>
      </ScreenReaderView>
      <p className="text-xs text-muted-foreground">
        No labels — turn on the emulation: every field announces as an unnamed text field (the placeholder is not a name).
      </p>
    </div>
  );
}
```

## Good — do this

`forms-labels-everywhere-good`

```tsx
import { ScreenReaderView } from '@/components/demo-kit/ScreenReaderView';

export function LabelsEverywhereGood() {
  return (
    <div className="w-full max-w-sm space-y-4">
      <ScreenReaderView>
        <div className="space-y-4">
          <div>
            <label htmlFor="full-name" className="block text-sm font-medium text-foreground mb-1">
              Full Name
            </label>
            <input
              id="full-name"
              type="text"
              className="w-full px-3 py-2 border border-border rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
              placeholder="John Doe"
            />
          </div>
          <div>
            <label htmlFor="email-address" className="block text-sm font-medium text-foreground mb-1">
              Email Address
            </label>
            <input
              id="email-address"
              type="email"
              className="w-full px-3 py-2 border border-border rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
              placeholder="john@example.com"
            />
          </div>
          <div>
            <label htmlFor="phone-number" className="block text-sm font-medium text-foreground mb-1">
              Phone Number
            </label>
            <input
              id="phone-number"
              type="tel"
              className="w-full px-3 py-2 border border-border rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"
              placeholder="+1 (555) 000-0000"
            />
          </div>
        </div>
      </ScreenReaderView>
      <p className="text-xs text-success">
        Each input announces with its label — turn on the emulation to hear the names ship.
      </p>
    </div>
  );
}
```

## References

- [MDN: Label element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/label)
- [WebAIM: Creating Accessible Forms](https://webaim.org/techniques/forms/)
