Labels & Structure

+15 Mana ✨

Proper labels and structure make forms usable for everyone, including users of screen readers and keyboard-only users.

Always Use Labels

Every input needs an associated label:

jsx
// ✅ Method 1: Wrapping (implicit)
<label>
  Email
  <input type="email" name="email" />
</label>

// ✅ Method 2: htmlFor (explicit)
<label htmlFor="email">Email</label>
<input id="email" type="email" name="email" />

// ❌ Bad: No label association
<span>Email</span>
<input type="email" name="email" />

Placeholders Are Not Labels

jsx
// ❌ Bad: Placeholder as only label
<input placeholder="Enter your email" />

// ✅ Good: Real label with optional placeholder
<label htmlFor="email">Email</label>
<input 
  id="email" 
  placeholder="you@example.com"
/>

Placeholders disappear when typing, leaving users confused about what field they're in.

Grouping with Fieldset

jsx
<fieldset>
  <legend>Shipping Address</legend>
  
  <label htmlFor="street">Street</label>
  <input id="street" name="street" />
  
  <label htmlFor="city">City</label>
  <input id="city" name="city" />
  
  <label htmlFor="zip">ZIP Code</label>
  <input id="zip" name="zip" />
</fieldset>

Radio Button Groups

jsx
<fieldset>
  <legend>Preferred Contact Method</legend>
  
  <label>
    <input type="radio" name="contact" value="email" />
    Email
  </label>
  
  <label>
    <input type="radio" name="contact" value="phone" />
    Phone
  </label>
  
  <label>
    <input type="radio" name="contact" value="mail" />
    Mail
  </label>
</fieldset>

Required Fields

jsx
<label htmlFor="name">
  Name <span aria-hidden="true">*</span>
  <span className="sr-only">(required)</span>
</label>
<input 
  id="name" 
  name="name" 
  required 
  aria-required="true"
/>

Note: The visual asterisk is hidden from screen readers, which announce "required" from the attribute instead.

✓ Completed