Forms

Missing labels, broken autocomplete, punitive validation. A respect problem.

Most form abandonment isn't about the number of fields. It's about the wrong keyboard appearing, autocomplete not firing, or an error message that says "invalid input" instead of what to fix.

Labels are not optional

Every input needs a visible label. Placeholders vanish on typing.

No room for a visible label? Use a visually-hidden one.

Placeholders are examples, not labels

Show the shape of the answer, not a paraphrase of the label:

WCAG requires 4.5:1 on placeholder text. Most designs fail this:

Autocomplete

Use exact spec values. autocomplete="new-password" triggers password generation. autocomplete="current-password" triggers saved credentials. Wrong values mean wrong autofills.

Never use autocomplete="off" on auth fields.

inputmode for the right keyboard

type="number" adds spinners. inputmode="numeric" gives the keyboard without spinners.

Enter-to-submit

Single-line forms submit on Enter by default when <button type="submit"> exists inside <form>. React onClick-only handlers break this.

Multi-line: Enter inserts newline, Cmd/Ctrl+Enter submits.

Inline errors

On failure, focus the first error. Be specific: "Email is required", not "Invalid input."

Keep submit enabled. Show all errors on click. Disable only during the request.

Submission state

  1. Disable the button to prevent double-clicks.
  2. Keep the original label. Add a spinner alongside it.
  3. On success, restore the button and confirm.
  4. On failure, restore the button and surface an actionable error.

Don't swap the label to Saving…. The button jumps width and translations break.

Collect form data first, then disable, then send. Warn on navigation with unsaved changes:

Mobile font size: the 16px rule

iOS Safari zooms the page when input font-size is below 16px.

Override on desktop only:

Tailwind text-sm is 14px. The most common offender.

Never block paste

Validate after paste:

Common mistakes