form / fieldset take the state of their controls

form:valid
form:valid, no controls
— an empty form is valid —
form:valid, barred control
fieldset:valid
form:invalid
x
fieldset:invalid, nested

step

step=2, off the grid
step base is min
step base is the value attr
step=any
step=0.1, decimal exactness
step, no value — an empty field has nothing to snap —

pattern

pattern, plain
pattern is anchored
alternation binds whole
empty value, no pattern test — that is `required`'s job —
a pattern that will not compile — the constraint does not apply —

minlength / maxlength (dirty values only)

maxlength, from markup — markup alone never overflows —
maxlength, set by script — nor does an assignment to .value —
minlength, set by script — the same, the other way round —

By hand: type abcd into the first field below (limit 3) and ab into the second (minimum 4). Both should turn red as you type; leaving them untouched must leave them black.

:user-valid / :user-invalid, and restyling as you type

These three are all by hand -- the whole point of them is that nothing happens until the user edits the control, and that the page then restyles without any script.

:user-invalid red once you type something that is not an address, black before
:user-valid green once you type a real address, black before
:invalid, live red while empty, green as soon as a character lands