sfw/fix
select-name critical

Select element must have an accessible name

A <select> has no label, aria-label, or aria-labelledby, so screen readers announce only "combobox" with no hint of its purpose.

What you see

Select element must have an accessible name (select-name)
Fix any of the following:
  Form element does not have an implicit (wrapped) <label>
  Form element does not have an explicit <label>
  aria-label attribute does not exist or is empty
<select id="country"><option>United States</option>...</select>

What’s actually happening

A <select> dropdown has nothing tying a name to it — no <label for>, no aria-label, no aria-labelledby. axe maps this to WCAG 4.1.2 Name, Role, Value. A screen reader lands on it and says "combobox" and the current option, with zero indication of what the dropdown is for; is it country, quantity, state, or sort order? The user has to guess from context or the selected value. It still drops down and works with a mouse, so it sails through visual QA. This is the <select>-specific case, separate from the generic input-label rule — a dropdown that opens fine but announces no purpose.

Common causes

  • A visible text label sits next to the dropdown but is never wired to it with for/id
  • The label's for value doesn't match the select's id (typo, missing id, or a duplicated id elsewhere on the page)
  • The dropdown is identified only by a placeholder-style first <option> ("Select a country"), which is not an accessible name
  • An icon or visual cue communicates purpose to sighted users but leaves nothing for assistive tech
  • A custom select component renders a native <select> under styling while the label lives in a sibling <div> that's never associated

How to fix it

  1. Wire a <label for> to the selectGive the select an id and point a label at it: <label for="country">Country</label><select id="country">. The id must be unique across the page — a duplicate silently breaks the link even though the markup looks right. Clicking the label text should focus the dropdown; if it does, the association holds.
  2. Hide the label visually if the design has no roomWhen the layout can't show a label, keep one in the DOM and hide it with a visually-hidden / sr-only class (clip it, don't use display:none, which strips it from the accessibility tree). Screen readers still read it; the screen stays clean.
  3. Use aria-label when there's no text to point atIf nothing on the page can serve as the label, put it on the element directly: <select aria-label="Sort order">. If a visible heading already names it, reference that by id with aria-labelledby instead of repeating the string. A placeholder first option doesn't count — axe won't accept it and screen readers skip it.
  4. Re-run the check against the rendered DOMRun axe or Lighthouse again and confirm select-name is gone. Inspect the live DOM, not the template — framework hydration sometimes drops the for/id pairing you authored, so the source can look correct while the shipped page fails.

Stop it recurring

Add an automated axe check (jest-axe, cypress-axe, @axe-core/playwright) to CI so an unlabeled <select> breaks the build instead of reaching production.

Related errors