What it asks for, in plain English
Each form control needs a visible label that says what goes in it. When there is a format, limit or requirement the person could not guess (date order, password rules, which fields are required), the form has to say so before they get it wrong.
A placeholder inside the field is not a label. It vanishes when you start typing, is usually too pale to read, and is not treated as a label by all assistive technology. The label should stay visible and be linked to the field in code, so clicking it focuses the field and a screen reader reads it with the field.
Instructions can be general ("All fields are required unless marked optional") or next to the field ("Day, month, year, for example 31 3 1985"). Put them before the field so they are read first.
This is an independent explanation. The binding wording is the W3C Recommendation, and the W3C's own Understanding 3.3.2 page has the full intent, techniques and definitions.
Who it affects
A screen reader user lands on an unlabelled field and hears only 'edit text', with no idea what to type.
Someone with a memory impairment starts typing, the placeholder disappears, and they can no longer remember what the field was for.
A person using voice control says "click Email" to reach a field, which only works if the field has a visible label with that word.
Example
Placeholders only. Start typing and the prompt is gone; nothing says which fields are required or what date format is expected.
Labels stay on screen, the optional field is marked, and the date field explains its format before anyone types.
Show the markup behind both examples
<style>body{margin:0;padding:16px;font-family:system-ui;font-size:14px}input{font:inherit;display:block;padding:6px 8px;border:1px solid #9ca3af;border-radius:4px;width:220px;margin-bottom:10px}input::placeholder{color:#c4c9d0}button{font:inherit;padding:6px 12px}</style>
<form>
<input placeholder="Full name">
<input placeholder="Email">
<input placeholder="Membership number">
<input placeholder="Date joined">
<button type="button">Save</button>
</form>
<style>body{margin:0;padding:16px;font-family:system-ui;font-size:14px}label{display:block;font-weight:600;margin-bottom:2px}.hint{display:block;color:#4b5563;font-size:13px;margin-bottom:4px}input{font:inherit;display:block;padding:6px 8px;border:1px solid #9ca3af;border-radius:4px;width:220px;margin-bottom:10px}p{margin:0 0 10px;color:#4b5563}button{font:inherit;padding:6px 12px}</style>
<form>
<p>All fields are required unless marked optional.</p>
<label for="name">Full name</label>
<input id="name" autocomplete="name">
<label for="email">Email</label>
<input id="email" type="email" autocomplete="email">
<label for="mem">Membership number (optional)</label>
<input id="mem">
<label for="joined">Date joined</label>
<span class="hint" id="joined-hint">Day, month, year, for example 14 6 2024</span>
<input id="joined" aria-describedby="joined-hint">
<button type="button">Save</button>
</form>
How to check it
- Look at each field. There should be a visible label that stays on screen while you type, not just a placeholder.
- Click each label. If the field gets focus, the label is linked correctly.
- Check that required fields and any format rules (dates, phone numbers, password length) are explained before you submit.
- Tab through the form with a screen reader and confirm each field is announced with its label and any hint.
What Websight checks for 3.3.2
Websight runs this automated check for 3.3.2:
Websight checks that every input, select and textarea has an accessible name, and flags a field that has two conflicting labels. It cannot judge whether the label is clear, whether it is visible, or whether the instructions are enough; a person has to read them.
Practical tips
- Use a label element with a for attribute matching the field's id; it is the simplest thing that works everywhere.
- If most fields are required, mark the optional ones instead.
- Put format hints in text under the label and link them with aria-describedby.
Other criteria in guideline 3.3, Input Assistance
- 3.3.1 Error Identification (level A)
- 3.3.3 Error Suggestion (level AA)
- 3.3.4 Error Prevention (Legal, Financial, Data) (level AA)
- 3.3.7 Redundant Entry (level A)
- 3.3.8 Accessible Authentication (Minimum) (level AA)