1<form action="/join">2 <label>Email3 <input name="email"4 type="email" required>5 </label>6 <label>Age7 <input name="age"8 type="number" min="13">9 </label>10 <button>Join</button>11</form>example.com/signupEmailAgeJoin!Please fill out this field.!Value must be greater than or equal to 13.Thanks for joining!Rejected: check your details.email.validityvalueMissingtruetypeMismatchfalsevalidfalseage.validityrangeUnderflowfalsevalidtrue/joinsaved ✓rejected ✗kimkim@example.com915?email=kim&age=9
Back left: the form's HTML; front left: each field's validity flagsBack right: the browser, which checks the form before sending itChips: typed values, the browser's check, and the form travelling to the serverBack left: signup.html, a form whose rules are attributes (required, type="email", min="13"). Back right: a browser showing the form. Front left: each field's validity record, true/false flags. Typed values hop from the keyboard into the fields and the flags change at once. Pressing Join sends the browser's magnifier to the first broken field and a message appears; nothing is sent until every field is valid. Then an envelope carries the form to the server at /join, and an address typed by hand shows why the server must check again. The figure stacks the two fields to keep them large. With no CSS, labels, fields and the button are inline, so the browser places them side by side and wraps them to the window's width.

Rules in the HTML

  1. A form collects what people type and sends it to a server. Validation checks that input first. In HTML you write the rules as attributes, and the browser checks them itself before anything is sent. No JavaScript is needed.

Pressing Join

Valid, sent, checked again

What happens

;; step 1/12 · check-first
file     signup.html   (a form: two fields, one button)
   1  <form action="/join">
   2    <label>Email
   3      <input name="email"
   4        type="email" required>
   5    </label>
   6    <label>Age
   7      <input name="age"
   8        type="number" min="13">
   9    </label>
  10    <button>Join</button>
  11  </form>
rules    attributes on the inputs; the browser checks them

The validity record changes the moment the value changes, but the browser only shows a message when the form is submitted (or when JavaScript calls reportValidity()). CSS can style broken fields as you type with the :invalid pseudo-class, or only after the person has interacted with them with :user-invalid. The words in the message bubbles are Chrome's. The HTML standard says the browser must report the problem, not which words to use, so Firefox and Safari word them differently.