A placeholder looks like a label right up until the user starts typing. Then the only hint about what the field wants is gone.
Web HIG tip #4 (Quick #50, #55, #80): Every form field needs a visible, associated label. Placeholders are not labels.
Why it matters
Placeholder-only fields look clean in a mockup and fail in real use:
- The hint disappears on the first keystroke, so people forget what the field was asking for
- Reviewing a filled form is guesswork: "Is this my work email or my personal one?"
- Placeholder text is usually low-contrast gray, which is hard to read and easy to mistake for a value that's already filled in
- Screen readers may not announce a placeholder reliably as the field's name
- Browser autofill fills the field, and the placeholder hint is gone before the user ever sees it
The rule of thumb
Ask: if the field is filled in, can someone still tell what it's for?
If not, it needs a real label.
<!-- Don't: the hint vanishes as soon as you type -->
<input type="email" placeholder="Work email">
<!-- Do: a visible label that stays, tied to the field -->
<label for="work-email">Work email</label>
<input id="work-email" type="email" autocomplete="email"
aria-describedby="work-email-hint">
<p id="work-email-hint">We'll send the invoice here.</p>
A placeholder can still help with an example format, like name@example.com. It just can't be the only thing telling people what the field is.
Do this instead
- Give every field a visible
<label>linked withforandid, or wrap the input inside the label - Put hints and errors in text below the field, and connect them with
aria-describedby - Mark required fields in text or with an icon that has a text alternative. Don't rely on color alone
- Use the right
typeandautocompleteso browsers and password managers can help
Quick check for your app
Fill in one form completely, then read it back without clicking anything. Every field should still say what it is. Then run a screen reader across the form: each field should be announced by its label, along with any hint or error attached to it.
The Web HIG is a behavioral contract for how the web should behave, not a component library. Design systems define look. The Web HIG defines behave.
- Docs: https://frozonfreak.github.io/webhig/
- Quick Reference: https://github.com/frozonfreak/webhig/blob/main/HIG-QUICK.md
- Tip discussion: https://github.com/frozonfreak/webhig/discussions/12
- Repo: https://github.com/frozonfreak/webhig
Top comments (2)
For the example-format placeholder, I'd use
name@example.comrather thanname@company.com, becausecompany.comis a real domain that has been registered since 1994, and example text has a way of ending up in test data and screenshots. RFC 2606 reservesexample.com,example.netandexample.orgfor exactly this. Phone hints work the same way: Ofcom sets aside London 020 7946 0xxx for drama and NANPA reserves 555-0100 to 555-0199 as fictitious, so +44 20 7946 0958 or +1 212 555 0123 shows the format without pointing at a real subscriber.Thanks, Elijah—good catch. name@example.com is a better choice here, and I’ll change the example. Your point about example text finding its way into test data and screenshots is a useful addition.
Thanks for the phone-number references too. A good companion rule to the post: keep labels persistent, and choose example details that won’t accidentally point to real people or businesses.