3 minute read

Forms Are Where Dreams Go to Die

Or: Why your form fields need therapy

Forms are where things get done. Sign up. Check out. Book an appointment.

But they’re also where things go wrong – especially if the form forgets there’s a human on the other side.

Think about the last time you filled out a really bad form. Maybe it was a government website, or some ancient e-commerce checkout. You start filling it out, get halfway through, and suddenly you’re lost. What format does the phone number want? Why did that field turn red? What does “Invalid input” even mean?

Now imagine that frustration, but you can’t see the visual cues that help most people navigate forms. Or your hands shake, making precise clicking difficult. Or you’re using voice commands because you can’t use a keyboard or mouse at all.

Suddenly, “slightly annoying” becomes “completely impossible.”

Labels: Not Optional, Not Negotiable

Picture this: You’re filling out a form, get distracted by a phone call, come back to your computer, and… what was that field for again? The placeholder text that told you what to enter vanished the moment you started typing.

Now you’re playing detective with your own form.

Placeholder text is not a label. I’ll say it again for the people in the back: Placeholder text is not a label.

The broken way:

<!-- Bad: Placeholder disappears when typing -->

<input type="email" placeholder="Email">

Why it hurts:

  • Placeholder disappears when typing
  • No context for screen readers
  • Forgotten what field you’re in after distraction
  • Poor contrast on most backgrounds

The right way:

<!-- Good: Properly associated label -->
<label for="email">Email address</label>

<input type="email" id="email">

<!-- Also good: Wrapped label -->

<label>

  Email address

  <input type="email">

</label>

<!-- Even better: With helpful context -->

<label for="email">

  Email address

  <span class="hint">We'll only use this to send your receipt</span>

</label>

<input type="email" id="email" name="email" autocomplete="email">

Why this matters:

  • Screen readers announce the label when focusing the field
  • Clicking the label focuses the input (bigger click target!)
  • Labels don’t disappear when you start typing
  • Labels can include formatting hints and requirements

Error Messages That Actually Help

“There was an error” is not helpful. It’s like someone saying, “You did something wrong” and walking away.

Here’s what’s wild: developers spend hours crafting the perfect user experience for the happy path – when everything goes right. But when something goes wrong? “Error. Try again.” That’s it. That’s the message.

Imagine if human conversations worked like this: “Could you pass the salt?” “Invalid request.” “…what?” “Invalid request.”

Tell people what went wrong and how to fix it.

<!-- Bad: Vague and unhelpful -->

<input type="email" aria-invalid="true">

<span class="error">Invalid input</span>

<!-- Good: Clear and actionable -->

<label for="email">Email address</label>

<input 

  type="email" 

  id="email"

  aria-invalid="true"

  aria-describedby="email-error"

>

<span id="email-error" class="error">

  Please enter a valid email address, like name@example.com

</span>

// Be specific in your validation messages

if (!email.includes('@')) {

  showError("Please include an '@' in your email address");

}

if (password.length < 8) {

  showError("Password must be at least 8 characters");

}

Good error messages:

  • Appear near the field they relate to
  • Explain what went wrong
  • Tell users how to fix it
  • Are announced by screen readers (using aria-describedby)
  • Don’t rely on color alone

The Magic of Autocomplete

You know when you click into the first address field and your whole address just appears like it read your mind? That’s not magic – that’s just good HTML.

This one’s so easy it hurts. Add autocomplete attributes, save everyone time:

<label for="name">Full name</label>

<input type="text" id="name" autocomplete="name">

<label for="email">Email</label>

<input type="email" id="email" autocomplete="email">

<label for="new-password">New password</label>

<input type="password" id="new-password" autocomplete="new-password">

<label for="cc-number">Card number</label>

<input type="text" id="cc-number" autocomplete="cc-number">

Common autocomplete values developers forget:

  • name, given-name, family-name
  • email, tel
  • street-address, address-line1, postal-code
  • cc-number, cc-exp, cc-csc

It’s free UX improvement. Use it.

→ Forms giving you grief?

Previous articleNext article
Back to top