ARIA input fields must have an accessible name
Estimated effort: about 10 minutes.
Custom form-style widgets built out of non-form elements (a <div> with role="combobox", role="searchbox", role="slider", role="spinbutton", or role="textbox", for example) do not get a name from a native <label for="..."> the way a real <input> does. If the widget has no aria-label or aria-labelledby, a screen reader announces it as an unlabeled field, such as a custom quantity spinner or an autocomplete search box on a product-listing page.
How to fix it
- Find custom widgets carrying an ARIA input role — role="combobox", role="listbox", role="searchbox", role="slider", role="spinbutton", or role="textbox" — that are built on a <div> or <span> rather than a native form element.
- Because a wrapping <label for="..."> does not work on non-form elements, add an aria-label directly on the element with the role, e.g. aria-label="Quantity" on a custom role="spinbutton" quantity stepper.
- Alternatively, if visible label text already exists nearby (e.g. a <span id="qty-label">Quantity</span> next to a custom stepper), reference it with aria-labelledby="qty-label" on the role="spinbutton" element instead of duplicating the text.
- This applies separately from, and in addition to, giving the widget the other required ARIA states (e.g. aria-valuenow on a spinbutton) — a name and a value are both required but are not substitutes for each other.
- Test with a screen reader or the browser's Accessibility Inspector to confirm the widget now announces both a name and its current value.
Before and after
Before
Custom quantity stepper built without a native <input>:
<div role="spinbutton" aria-valuenow="1" aria-valuemin="1" aria-valuemax="10" tabindex="0">1</div>
After
<div role="spinbutton" aria-label="Quantity" aria-valuenow="1" aria-valuemin="1" aria-valuemax="10" tabindex="0">1</div>