ADA Compliance Professionals

    Avoid multiple labels on form fields

    Last updated:

    Who it helps:
    Blind
    Standard:
    WCAG 2.2 Level A

    Form fields must not have multiple labels

    Each form control must expose one programmatic label (accessible name).

    This issue appears when a single input, select, or textarea is associated with more than one label or name source.

    It affects screen reader users, voice control users, and anyone relying on clear, consistent form interactions.

    Why It Matters

    When more than one label is tied to the same control, assistive technologies can announce different text depending on the browser or AT. Some read the first label, some the last, others combine them. This inconsistency confuses users and slows form completion.

    Voice control users may experience mismatches between what is visible and what the system expects them to say, causing commands to fail.

    This problem undermines perceivable relationships (WCAG 1.3.1), name/role consistency (WCAG 4.1.2), and clear labeling (WCAG 3.3.2).

    Common Causes

    • Two or more label elements pointing to the same id via for attributes.
    • Wrapping a control in a label while also using a separate label for="...".
    • Combining a label element with aria-labelledby that references additional nodes as names.
    • Using both aria-label and a label element on the same control.
    • Adding instructions or status text as extra label elements instead of descriptions.
    • Relying on the title attribute as an additional label source.

    How to Fix

    1. Provide exactly one accessible name per control.
      • Preferred: one label element associated with the control (either wrapping or using for=). Do not do both.
      • Avoid mixing label with aria-label or aria-labelledby unless you intentionally replace the label entirely.
    2. Move extra text into descriptions, not labels.
      • Use aria-describedby to attach help text, examples, and error messages.
      • Keep the label concise; keep guidance in separate elements referenced by aria-describedby.
    3. Group related options correctly.
      • For radio or checkbox groups, use fieldset and legend for the group question.
      • Give each option one label. Do not add a second label for group instructions.
    4. Do not use title for required labeling.
      • Title is unreliable across platforms and should not be the main label.
    5. Validate associations.
      • Each control’s id should match at most one label’s for attribute, or be wrapped by one label—not both.
      • Remove any redundant aria-labelledby or aria-label when a label element is present.

    Recommendation: If you must compute a name from multiple text nodes, use aria-labelledby alone and omit the label element to avoid multiple name sources. Ensure the visible text matches the computed accessible name.

    How to Test

    Keyboard check

    • Tab through all fields. Each field should receive focus once, and pressing a label should toggle/activate only its associated control.

    Screen reader check

    • With NVDA or JAWS (Windows) and VoiceOver (macOS/iOS) or TalkBack (Android), navigate by form fields.
    • Each control announces one clear label plus the control type (e.g., “Email, edit”). No duplicated or conflicting label text.

    Mobile/touch check

    • Tap labels. Only the intended control activates or toggles.
    • Screen reader does not repeat multiple labels for the same control.

    Quick automated check

    • Run an automated scanner (e.g., axe, Accessibility Insights) to flag multiple labels or conflicting name sources.

    Good Example

    HTML
    <label for="email">Work email</label>
    <div id="email-hint">Use your company address.</div>
    <input id="email" name="email" type="email" aria-describedby="email-hint email-error" aria-invalid="false">
    <!-- Error message is injected on validation when needed -->
    <div id="email-error" class="visually-hidden" aria-live="polite"></div>
    
    <fieldset>
      <legend>Preferred contact method</legend>
      <div>
        <input type="radio" id="contact-email" name="contact" value="email">
        <label for="contact-email">Email</label>
      </div>
      <div>
        <input type="radio" id="contact-phone" name="contact" value="phone">
        <label for="contact-phone">Phone</label>
      </div>
    </fieldset>

    Bad Example

    HTML
    <!-- Two labels pointing to the same input -->
    <label for="user">Username</label>
    <label for="user">Account ID</label>
    <input id="user" type="text">
    
    <!-- Mixed nested label and for= label on the same control -->
    <label for="tos">Terms of Service</label>
    <label><input id="tos" type="checkbox"> I accept the terms</label>
    
    <!-- Label plus aria-labelledby creating multiple name sources -->
    <label id="city-label" for="city">City</label>
    <span id="city-extra">(required)</span>
    <input id="city" type="text" aria-labelledby="city-label city-extra">

    Quick Checklist

    • Exactly one label source per control (label OR aria-*), not both.
    • Use label for the primary name; use aria-describedby for help, examples, and errors.
    • Do not wrap and for= the same control at once.
    • No duplicate label elements targeting the same id.
    • For groups of radios/checkboxes, use fieldset/legend plus one label per option.
    • Avoid title as a label; it is not reliable.
    • Screen readers announce one clear label and the correct control type.
    • Automated tests show no multiple labels or conflicting accessible names.