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
- 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.
- 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.
- 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.
- 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.