( Perceivable / WCAG 1.3.1 )

Input only uses placeholder as its label

SeriousLevel AWCAG 1.3.1 — Info and Relationships

What is this issue?

A form input, select, or textarea has a placeholder attribute rendering example or hint text inside the empty field, but no <label for> pointing at its id, no aria-label, no aria-labelledby, and no wrapping <label> element. Visually, the gray placeholder text sitting inside the field can look enough like a real label that the gap is easy to miss during a quick visual check.

The placeholder attribute was designed as a short-lived hint (an example value or format cue), not as a substitute for a real, persistent name. Nothing about it creates the DOM-level connection assistive technology relies on to identify the field.

Why does this matter?

A placeholder vanishes the exact moment a user types their first character, which means the field’s only visible clue about its purpose exists for as long as it takes to start filling it in, and then it’s gone for the rest of the interaction. Anyone who glances away and back, gets interrupted mid-form, or simply has multiple similar-looking empty-but-now-filled fields in view has no way to re-check what a field was asking for without clearing it and starting over.

For fields that also lack any programmatic label, this compounds with an accessibility failure on top of the usability one: some screen readers announce placeholder text as a last-resort fallback name, others don’t announce it at all, so the same field can be silently unlabeled for one user and inconsistently, temporarily labeled for another, with no reliable behavior either way.

Who is affected?

  • Screen reader users: get either no name at all or an inconsistent, browser-dependent fallback announcement of the placeholder text, since screen reader support for reading placeholder as a name varies across tools.
  • Low vision: using screen magnification see only a small portion of the page at a time; once a placeholder disappears on typing, there’s no way to scroll back to a persistent label that never existed in the first place, unlike a real label positioned outside the input.
  • Cognitive disabilities: including short-term memory difficulties, lose the field’s only identifying hint the moment they start typing, forcing them to clear their input and re-read the vanished placeholder to confirm what they were meant to enter.

What users experience

Sofia has ADHD and frequently gets interrupted mid-task while filling out online forms. She’s midway through a multi-field checkout using Chrome with no assistive technology, and after a brief interruption returns to a “Promo code” field she’d filled with placeholder-only text earlier in the flow. The placeholder vanished the moment she typed into it, so the field now just shows her partial input with nothing indicating what it was originally asking for. She has to delete what she typed, wait for the placeholder to reappear, re-read it, and then retype her code from scratch, a step a persistent visible label would have made entirely unnecessary.

How do I fix it?

Add a persistent, visible <label> element connected to the input with a matching for/id pair. This works because a real label stays on screen and in the DOM for the entire interaction, unlike a placeholder that exists only until the first keystroke, and it gives every screen reader a consistent, reliably-announced name regardless of fallback behavior differences.

Keep the placeholder if it still adds value as a format example: showing e.g. sarah@example.com next to a real “Email address” label is a genuinely useful supplementary hint. The placeholder just can’t be the field’s only source of identification. If a visible label would be redundant, such as a single search box next to a recognizable magnifying-glass icon, use a visually-hidden <label> or CSS technique that keeps the label in the accessibility tree without displaying it on screen, rather than relying on the placeholder alone.

Code Examples

Before
<input type="text" placeholder="Full name">
<input type="email" placeholder="Email address">
After
<div class="field">
  <label for="name">Full name</label>
  <input type="text" id="name" placeholder="e.g. Sarah Johnson">
</div>
<div class="field">
  <label for="email">Email address</label>
  <input type="email" id="email" placeholder="e.g. sarah@example.com">
</div>

Both fields now have a persistent, programmatic <label> supplying their accessible name, while the placeholder is repurposed as a supplementary format example rather than the field’s only identifying text. The label survives every keystroke; the placeholder’s original job of showing an example value is exactly what it’s still doing.

Common Mistakes

Mistake: “The placeholder text already says what the field is, so a label would be redundant.” A placeholder disappears the moment someone starts typing, so it can never fully substitute for a label that persists through the entire interaction. The two aren’t redundant, they serve different jobs, and only one of them is programmatic in the first place.

Mistake: “It looks fine: there’s clearly text inside the field explaining what to type.” Visual appearance during a quick glance at an empty form says nothing about what happens once the field has content, or about what a screen reader announces regardless of visual state. The failure is entirely in the DOM relationship, not the rendered look of an empty input.

Mistake: “Adding a title attribute alongside the placeholder should cover screen readers.” A title attribute is an unreliable fallback at best; several screen readers skip it, and it’s invisible to keyboard-only and touch users entirely, appearing only as a mouse-hover tooltip. It does not substitute for a real <label>, aria-label, or aria-labelledby.

How RedFlag Detects This

Custom automated: RedFlag’s own DOM detector, runs on every scan. RedFlag scans every input, select, and textarea that has a placeholder attribute (excluding hidden, submit, button, and reset types, which have their own naming rules), and flags any that has no <label for> pointing at its id, no aria-label, no aria-labelledby, and is not wrapped inside a <label> element.

False negative: the check only looks at inputs that actually have a placeholder set; a field with no placeholder and no label at all is a real failure but falls under RedFlag’s separate missing-label check instead, not this one. False positive: none typical for this specific check, since confirming the presence or absence of the four naming mechanisms alongside a placeholder is a straightforward DOM query. Manual step: for any flagged field, confirm the fix you add is a genuinely persistent label and not just another attribute that shares the same vanishing-on-input problem the placeholder had.

Manual Testing

  1. Open the page in Chrome or Firefox with NVDA or VoiceOver running.
  2. Tab to a field that shows gray hint text inside it before you start typing.
  3. Listen to what’s announced: it should be a specific, persistent name, not just the role alone and not an inconsistent read of the placeholder text.
  4. Type a character into the field, then tab away and back. Confirm there’s still a visible, persistent label on screen identifying the field, separate from whatever you just typed.

1.3.1 Info and Relationships: Information, structure, and relationships conveyed through presentation must also be available programmatically. Placeholder-only text is a visual-only cue with no DOM-level relationship to the field it describes, exactly the gap this criterion targets.

Form input has no label is the broader missing-label check this rule is a common, specific cause of; most placeholder-only fields are also, technically, unlabeled fields.

Related form inputs are missing fieldset and legend covers a different group-level labeling gap, for sets of related fields rather than a single field’s own name.

Form field has more than one label is the opposite direction of labeling failure: too many labels rather than a placeholder standing in for none at all.

Form field autocomplete attribute is missing or invalid commonly affects the same placeholder-only fields, since a field with no real label often has no purpose-identifying autocomplete attribute either.

Form error is not clearly identified compounds badly with placeholder-only fields: a user who’s already unsure what a field is for has an even harder time recovering from an error on it.

Select element has no accessible name is the same missing-label pattern applied to <select> controls, which lose their placeholder-as-label workaround entirely once the field is opened and a real option is chosen.

References

Frequently asked questions

Is a placeholder useless, or can it still be used for something?

It is still useful as a supplementary format hint alongside a real label, showing an example date format or a sample phone number, for instance. The problem is using it as the field's only naming mechanism, not using it at all.

Why do placeholder-only fields often look fine visually?

Because a placeholder renders as gray text inside the empty field, visually indistinguishable at a glance from a real label sitting above it; the failure is entirely in the underlying code, not in how the empty field looks on screen, which is exactly why it slips past visual review.

Does every screen reader announce placeholder text the same way?

No, support is inconsistent. Some browser and screen reader combinations announce placeholder text as a fallback name when nothing else is present, others announce nothing at all, meaning the same unlabeled field can behave completely differently depending on which tool a user happens to have.

Is this the same failure as Form input has no label?

They're closely related but distinct checks. Form input has no label covers any field missing a programmatic name for any reason. This rule specifically targets the common case where a placeholder is present and might visually look like a label, even though it still is not one.

Does adding aria-label alongside the placeholder fix this?

Yes. Adding aria-label gives the field a real programmatic name while the placeholder can stay in place as a supplementary hint; just make sure the aria-label text and the placeholder don't say contradictory things, since aria-label is what gets announced, not the placeholder.