Published:
Last Updated:
Tested with latest versions of screen readers and browsers available at time of publish.
label elements for one input=textlabel elements for one input=searchlabel elements for one input=tellabel elements for one input=urllabel elements for one input=emaillabel elements for one input=passwordlabel elements for one input=monthlabel elements for one input=datelabel elements for one input=weeklabel elements for one input=timelabel elements for one input=datetime-locallabel elements for one input=numberlabel elements for one input=rangelabel elements for one input=colorlabel elements for one input type=checkboxlabel elements for one input type=radiolabel elements for one input=filelabel elements for one input=submitlabel elements for one input=imagelabel elements for one input=resetlabel elements for one input=buttonlabel elements for one selectlabel elements for one textarealabel elements for one outputlabel elements for one meterlabel elements for one progresslabel elements for one buttonWebkit / AX will consistently drop the second label from an element's accessible name.
IE11 / MSAA will consistently drop the first label if an element is provided 2 for its accessible name.
    input type=color:
    Firefox PC - MSAA / IA2: push button
    Firefox PC - UIA: UIA_Button
    Chromium - MSAA accRole: editable text. IA2: Color Chooser. UIA: UIA_Edit
    Chromium - accName "Primary Secondary"
    JAWS bug filed.
  
    input type=file:
    Firefox PC - MSAA/IA2 expose "PrimarySecondary" as the accessible name.  NVDA and TalkBack(?) each appear to bypass the input's name and instead expose the subtree of the file input.
    Firefox PC - MSAA / IA2: push button
    Firefox PC - UIA: UIA_Button
    Chromium - MSAA/IA2 accValue/Value "No file chosen"
    Chromium - exposed as Push button
  
    input type=button
    Chromium - MSAA/IA2 expose value as accDescription/Description when label(s) provides accessible name.
  
    output
    Firefox PC - MSAA/IA2 expose "PrimarySecondary" as the accessible name.
  
    meter
    Firefox PC - MSAA/IA2 expose "PrimarySecondary" as the accessible name.
    Firefox PC - MSAA accRole: meter. IA2 Role: Text Frame.
    Chromium - MSAA/IA2/UIA all expose "Primary Secondary" as accessible name.
    Chromium - MSAA/IA2/UIA roles: progress bar and UIA_ProgressBar (should be updated)
  
    progress
    Firefox PC - MSAA/IA2 expose "PrimarySecondary" as the accessible name. Seems NVDA/JAWS should be updated to announce labels on progress bar.
    
    Chromium -
  
    button
    Firefox PC - MSAA/IA2 expose "PrimarySecondary" as accName.
    Chromium - MSAA/IA2/UIA expose "Primary Secondary" as accName.
  
Expectation: Both labels should contribute to accessible name of element. Screen readers should announce both labels.
| Browser / Screen Reader | Firefox JAWS | Firefox NVDA | Firefox TalkBack | Chrome + JAWS | Chrome + NVDA | Chrome + TalkBack | Chrome + VoiceOver (macOS) | Safari + VoiceOver (macOS) | Safari + VoiceOver (iOS) | IE11 + JAWS | IE11 + NVDA | Edge + JAWS | Edge + NVDA | 
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| input=text | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=search | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=tel | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=url | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=email | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=password | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=month | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=date | Pass | Pass | Fail TalkBack does not announce labels for segmented date input.  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=week | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=time | Pass | Pass | Fail TalkBack does not announce labels for segmented time input.  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=datetime-local | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=number | Pass Repeats first label  |  
        Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=range | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=color | Pass | Pass | Pass (but no space between words).  |  
        Fail (JAWS ignores) No announcement made. Both labels are exposed.  |  
        Pass (no role announcement)  |  
        Fail announced as hex value  |  
        Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Fail (JAWS ignores) No announcement made. Both labels are exposed.  |  
        Pass (no role announcement)  |  
      
| input=checkbox | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail announces second label THEN first label. NOTE: if both labels are in the DOM prior to the input, then only the first label will be announced.  |  
        Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=radio | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=file | Pass | Fail Does not announce either label, only announces "Browse, no file selected."  |  
        Fail Does not announce either label, only announces "Browse button"  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| input=submit | Pass Does not announce "Submit"  |  
        Pass Does not announce "Submit"  |  
        Pass (but no space between words). Does not announce "Submit"  |  
        Pass Does not announce "Submit"  |  
        Pass Does not announce "Submit"  |  
        Pass Does not announce "Submit"  |  
        Pass Does not announce "Submit"  |  
        Fail only exposes first label. "Submit primary"  |  
        Fail only exposes first label. Does not announce "Submit"  |  
        Fail Does not announce either label.  |  
        Fail only exposes second label. Does not announce "Submit"  |  
        Pass Does not announce "Submit"  |  
        Pass Does not announce "Submit"  |  
      
| input=image | Pass Does not announce "alt"  |  
        Pass Does not announce "alt"  |  
        Pass (but no space between words). Does not announce "alt"  |  
        Pass Announces "Primary Secondary Alt"  |  
        Pass Does not announce "alt"  |  
        Pass Does not announce "alt"  |  
        Pass Does not announce "alt"  |  
        Fail only exposes first label. "Primary, alt"  |  
        Fail only exposes first label. Does not announce "alt"  |  
        Fail Does not announce either label.  |  
        Fail Does not announce either label.  |  
        Pass Announces "Primary Secondary Alt"  |  
        Pass Does not announce "alt"  |  
      
| input=reset | Pass Does not announce "Reset"  |  
        Pass Does not announce "Reset"  |  
        Pass (but no space between words). Does not announce "Reset"  |  
        Pass Does not announce "Reset"  |  
        Pass Does not announce "Reset"  |  
        Pass Does not announce "Reset"  |  
        Pass Does not announce "Reset"  |  
        Fail only exposes first label. "Reset primary"  |  
        Fail only exposes first label. Does not announce "Reset"  |  
        Fail Does not announce either label.  |  
        Fail only exposes second label. Does not announce "Reset"  |  
        Pass Does not announce "Reset"  |  
        Pass Does not announce "Reset"  |  
      
| input=button | Pass Does not announce "Value"  |  
        Pass Does not announce "Value"  |  
        Pass (but no space between words). Does not announce "Value"  |  
        Pass "Value" announced as accessible description.  |  
        Pass "Value" announced as accessible description.  |  
        Pass "Value" announced as accessible description.  |  
        Pass "Value" announced as accessible description.  |  
        Fail only exposes first label. "Value primary"  |  
        Fail only exposes first label. Does not announce "Value"  |  
        Fail Does not announce either label.  |  
        Fail only exposes second label. Does not announce "Value"  |  
        Pass Announces "Primary Secondary Value"  |  
        Pass Announces "Primary Secondary Value"  |  
      
| select | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass | 
| textarea | Pass | Pass | Pass (but no space between words).  |  
        Pass | Pass | Pass | Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label.  |  
        Fail only exposes second label.  |  
        Pass | Pass |  
      
| output | Pass Exposes both labels as accessible name. JAWS virtual cursor only announces visible text.  |  
        Pass Exposes both labels as accessible name. NVDA virtual cursor only announces visible text.  |  
        Fail No role announced or accessible name from labels announced when focusing output.  |  
        Pass Exposes both labels as accessible name. JAWS virtual cursor only announces visible text.  |  
        Pass Exposes both labels as accessible name. NVDA virtual cursor only announces visible text.  |  
        Pass But contents of output are not announced.  |  
        Fail Both labels exposed as accessible name but no role announced or accessible name from labels announced when focusing output.  |  
        Pass Announces as: "Primaryvalue Secondary" or "PrimarySecondary" if no text within output.  |  
        Fail only exposes first label.  |  
        Fail Role not exposed by IE  |  
        Fail Role not exposed by IE  |  
        Pass Exposes both labels as accessible name. JAWS virtual cursor only announces visible text.  |  
        Pass Exposes both labels as accessible name. NVDA virtual cursor only announces visible text.  |  
      
| meter | Pass But value of meter not announced.  |  
        Pass But value of meter not announced. No role announced.  |  
        Fail Element ignored.  |  
        Fail Exposes both labels as accessible name. JAWS virtual cursor only announces value and role of meter.  |  
        Pass (element announced as progress bar). No value announced.  |  
        Pass But value of meter not announced.  |  
        Pass |  
        Fail only exposes first label.  |  
        Fail ignored  |  
        Fail Element not rendered by IE  |  
        Fail Element not rendered by IE  |  
        Fail Exposes both labels as accessible name. JAWS virtual cursor only announces value and role of meter.  |  
        Pass (element announced as progress bar). No value announced.  |  
      
| progress | Fail Exposes both labels as accessible name. JAWS virtual cursor only announces value and role for progress bar.  |  
        Fail Exposes both labels as accessible name. NVDA virtual cursor only announces value and role for progress bar.  |  
        Pass (but no space between words).  |  
        Fail Exposes both labels as accessible name. JAWS virtual cursor only announces value and role for progress bar.  |  
        Pass But value of progress not announced  |  
        Pass But value of progress not announced  |  
        Pass | Fail only exposes first label.  |  
        Fail only exposes first label.  |  
        Fail only exposes second label. JAWS does not announce.  |  
        Fail only exposes second label. NVDA does not announce.  |  
        Fail Exposes both labels as accessible name. JAWS virtual cursor only announces value and role for progress bar.  |  
        Pass But value of progress not announced  |  
      
| button | Pass If button contains no text, both labels. If button contains text, the labels will overwrite the visible text.  |  
        Pass If button contains no text, both labels. If button contains text, the labels will overwrite the visible text.  |  
        Pass If button contains no text, both labels announced. If button contains text, the labels will overwrite the visible text.  |  
        Pass If button contains no text, both labels announced but twice. If button contains text, the labels will overwrite the visible text.  |  
        Pass If button contains no text, both labels. If button contains text, the labels will overwrite the visible text.  |  
        Pass If button contains no text, both labels announced. If button contains text, the labels will overwrite the visible text.  |  
        Pass If button contains no text, both labels announced. If button contains text, the labels will overwrite the visible text.  |  
        Fail only exposes first label. If button contains content, will announce as "button text, first label"  |  
        Fail only exposes first label.  |  
        Fail If button contains no text, second label may be announced OR button's Value. If button contains text, labels not used for accessible name.  |  
        Fail If button contains no text, second label announced or "blank" if navigating by virtual cursor. If button contains text, labels not used for accessible name.  |  
        Pass If button contains no text, both labels announced but twice. If button contains text, the labels will overwrite the visible text.  |  
        Pass If button contains no text, both labels. If button contains text, the labels will overwrite the visible text.  |