Every input field — input, select, textarea — must have a label describing what's expected of the user. That label must be both visible on screen and programmatically tied to the field. This is criterion 11.1, and it's on the e-commerce checkout that it breaks the most.
The two correct ways
<label for="email">Email address</label>
<input id="email" type="email">
<!-- or, by nesting -->
<label>
Email address
<input type="email">
</label>In the first form, the label's `for` attribute points to the field's `id`: that's the programmatic link. In the second, the field is nested inside the label, which creates the link implicitly. Both are compliant; the first is the more robust because it's independent of the layout.
What is NOT enough
- →`<input placeholder="Email">` alone — the placeholder disappears on typing and is not a label
- →Text beside the field with no `<label for>` — visually it's a label, programmatically it isn't
- →`aria-label="Email"` on a visible field — accessible to the screen reader, but with no label shown for other users
- →A lone red asterisk to signal "required" — colour doesn't carry the information
Pitfall #1: the placeholder as a label
This is the most widespread anti-pattern. A field with only `placeholder="Name"` looks labelled while empty. As soon as the user types, the cue vanishes: impossible to check you're filling the right field, impossible to re-read. For older people and screen-reader users, the form becomes a maze. The placeholder is a complement, never a substitute for the label.
E-commerce special cases
The search field
The magnifying-glass icon doesn't act as a label. Add a visually hidden `<label>` (class `sr-only` / `screen-reader-text`) or, failing that, an `aria-label="Search for a product"` on the field.
Terms and newsletter checkboxes
The terms-acceptance checkbox must have a clickable label describing the commitment. A bare "I accept" placed next to an unlinked box is a frequent 11.1 failure at the end of the funnel.
⚠ PrestaShop / WooCommerce pitfalls
Third-party payment modules (Stripe Elements, PayPal Smart Buttons) inject their own fields, often inside an iframe. Many lack a proper label, and you can't always fix them from the theme. Check after each module update, and report the defect to the vendor if needed.
How to detect it
An engine like axe-core spots fields without an accessible name instantly. On the checkout, this is the criterion that blocks the most purchase funnels for blind users — so the one whose harm is most direct, and the legal argument the strongest in case of a complaint. A ComplAudit audit lists every unlabeled field with its DOM selector and the template file involved.
Frequently asked questions
aria-label or a visible <label>: which to choose?
Always a visible `<label>` when possible. `aria-label` only makes the field accessible to screen readers; it leaves sighted users who need a displayed label with no cue. Reserve `aria-label` for cases where a visible label is genuinely impossible.
Is a placeholder forbidden?
No. The placeholder is still useful to show an expected format ("dd/mm/yyyy"). It only becomes a problem when it replaces the label instead of complementing it.
Do read-only fields need a label?
Yes for visible read-only fields: the user must know what they contain. Genuinely hidden fields (`type="hidden"`) are not concerned.
Find every unlabeled field on your checkout, with its exact location:
→ Run an audit