Accessibility · Forms and Errors

Placeholders as a Fallback Name and Why They Fail

How the placeholder attribute enters the accessible name computation, why it ranks last, and the concrete failures that follow from using it as a label.

Placeholder text occupies the same box as the value it is meant to replace. That single fact generates every problem with it. A string drawn inside an empty input must disappear the moment the user types, must be distinguishable from a real value, and must not be mistaken for content, and the accessibility API has to decide what to call it, because a string that is neither a label nor a value has no obvious slot.

The specification’s decision is that placeholder is a name source of last resort. It ranks below aria-labelledby, aria-label, a <label>, and title in the accessible name computation, and it contributes nothing to the description. The consequence is that a field whose only text is a placeholder does get a name, which makes the field technically compliant and practically poor, because the name is now a string with properties that no name should have.

What the computation does with it

When a text input has no other name source, the placeholder’s text becomes the accessible name. The name is computed when focus enters the field, and the string is whatever the placeholder holds at that moment. If the placeholder changes, for instance a script swapping it for a format hint after a failed submission, the name changes with it. The accessible name is not cached across the session in any way the author can rely on.

Once the user types, the placeholder disappears from rendering but the name does not disappear from the accessibility tree. The name was computed from the attribute, and the attribute is still there. A screen reader user therefore hears “Email address” as the name of a field whose visible box no longer shows that text, which is the best case for the pattern and still leaves a mismatch between what a sighted and a non-sighted user can see at a glance.

The failure arrives when the placeholder is doing double duty as a format hint. A field with placeholder="DD/MM/YYYY" and no label has the accessible name “DD/MM/YYYY”. The user hears a name that is a format pattern, and the field’s actual purpose, date of birth, is nowhere in the accessibility tree. The name slot is occupied by the wrong kind of information, and there is no second slot for the purpose.

The four failures, mechanically

The name is a hint. A placeholder written as a format example or an example value takes the name slot. Names should answer “what is this field”, hints should answer “what form should the value take”, and the computation gives one slot at the top of the announcement. The standard remedy is a real label for the name and aria-describedby for the hint, which places the hint after the value rather than in the name. That ordering is discussed in Wiring Error Messages to Their Fields, because the same description slot carries error text.

The name vanishes from view. A sighted user who has typed into a field can no longer see what the field was for. This is a memory burden rather than a hard failure, and it compounds in long forms: by the tenth field, the earlier placeholders are gone and the only record of what each field asked is in the user’s head. It also interacts badly with error recovery, because a field in error is by definition a field with content, so its placeholder-derived label is invisible at exactly the moment the user needs to identify it.

Contrast is unconstrained. Placeholder text is rendered with the user agent’s default colour, which is deliberately de-emphasised, and authors routinely lighten it further to keep it distinct from real values. The WCAG contrast requirement of 4.5:1 for normal text applies to placeholder text as text. The failure is not in the requirement but in the visual logic: the darker the placeholder, the more it looks like a value; the lighter, the less it can be read. There is no setting that resolves both pressures, which is the argument for putting the string in a label outside the box where it can be full contrast without being confused for input.

The hint and the value are visually identical. Placeholder rendering differs from value rendering only by colour in most browsers. A user with low vision, or a user on a screen in daylight, can read a grey “Search products” inside a box as a prefilled search term. Submitting the form then sends an empty value where the user believed there was content, and the resulting validation error is confusing because the user did not know the box was empty.

The attribute also has legitimate uses

None of the above means the attribute should never be used. Its defined role is a short hint that helps with the expected value, and used as a supplement to a label it does that job.

<label for="phone">Mobile number</label>
<input id="phone" name="phone" type="tel"
       autocomplete="tel-national"
       placeholder="07700 900123"
       aria-describedby="phone-hint">
<p id="phone-hint">Include the leading zero. No spaces.</p>

Here the label supplies the name, the placeholder supplies a visual example that disappears on typing, and the described-by hint supplies the constraint that must persist. Three slots, three different jobs. The example is the one piece of information that is safe to lose on typing, because it has already served its purpose.

The distinction to hold onto is that a placeholder is an example, and an example is redundant with the format rule. When the format rule cannot be expressed as a pattern, as with “the name as it appears on the card”, the placeholder cannot express it either, and the hint slot is the only place for it.

Multi-line and non-text controls

On textarea the attribute behaves differently in one respect that matters: the placeholder occupies the whole box and is replaced by the first character typed, so a multi-line field with a long instructional placeholder loses all of it at once. A textarea with a 60-word placeholder as its only text is a field whose instructions disappear permanently after one keystroke.

A select element does not support the attribute at all, so the “choose an option” prompt must be a real <option> with an empty value, usually the first in the list. That option is selectable and, unless it is disabled as well as empty-valued, it is a legitimate answer that will fail server-side validation. The accessible name of the select still has to come from a label; the empty option does not name it.

The attribute applies to input and textarea, and within input it is not supported for types that render their own value affordance. type="date", type="color", and type="range" ignore it. A date field with placeholder="DD/MM/YYYY" shows nothing, and the browser’s own locale-dependent format is what the user sees, which is a good argument for putting the expected format in a described-by hint instead of relying on either the placeholder or the native rendering.

What replaces it

The replacement is a visible <label> element, associated explicitly, plus aria-describedby for anything that must persist. The label survives typing, survives autofill, survives a change of placeholder text, and is available to pointer users as a larger hit target; the association mechanics are in Label Association and the Accessible Name of a Form Control.

Where the design genuinely cannot accommodate a visible label, as with a single search box in a header, the options are an aria-label on the input, which gives the name without the visual, or a visually hidden <label>. Both are worse than a visible label for sighted users who benefit from persistent text, and both are strictly better than a placeholder, because they put the name in the name slot and leave the hint slot free.

The one thing that cannot be fixed after the fact is a name that was never computed from the right source. A placeholder-derived name is technically present and semantically wrong, and no amount of error-message work downstream repairs it: the error will be attached to a field the user cannot identify.

References

  1. HTML Living Standard: The placeholder attribute — WHATWG
  2. Accessible Name and Description Computation 1.2 — W3C
  3. Understanding Success Criterion 3.3.2: Labels or Instructions — W3C WAI