INDEPENDENT NOTES ON CODE & THE WEBGO · HTML · CSS
small systems
HTML / 3 minute read

Forms people can actually complete

Labels, input types, and useful validation are a better starting point than a clever floating placeholder.

Updated October 30, 2026Small Systems

Give every field a visible label

A placeholder disappears as soon as someone types. Keep the name of the field visible and connect it to the input using for and id. Put a hint beside the field when a format or constraint needs explanation.

html
<form action="/subscribe" method="post">
  <label for="email">Email address</label>
  <p id="email-hint">Used only for the monthly reading list.</p>
  <input
    id="email"
    name="email"
    type="email"
    autocomplete="email"
    aria-describedby="email-hint"
    required
  >
  <button type="submit">Subscribe</button>
</form>

Make the backend part of the design

This markup assumes that you have implemented a POST endpoint at /subscribe. HTML alone does not store the address or send a confirmation email. Build and test the server behavior before publishing the form, and explain what someone should expect after submission.

Validate on both sides

The browser can catch an empty required field or an obviously invalid email address. It cannot replace server validation. Treat client input as untrusted, apply size limits, and return a clear error without losing the values someone has already entered.

Keep errors close to the field

When the server renders an error, associate its text with the relevant input using aria-describedby and set aria-invalid="true". Say what went wrong and what to change. Avoid identifying an error through color alone; text and a visible border give more people a usable signal.

Keep reading in the original documentation:
HTML forms specification ↗