Forms in depth: validation, autocomplete and mobile keyboards
Use the Constraint Validation API for custom messages, autocomplete tokens so browsers fill forms, inputmode and enterkeyhint for the right mobile keyboard, FormData, and :user-invalid styling.
Comes up in: Web fundamentals, UI coding, Machine coding
Learn#
Neha’s sign-up form shows “Please match the requested format.” for a PIN code. Users do not know what format. Half of them leave.
Browsers validate forms from HTML attributes (required, type="email", pattern, min). Constraint validation is the API to read and control that from JavaScript: validity says what is wrong, setCustomValidity() sets your message, and reportValidity() shows it.
const form = document.createElement("form");
form.innerHTML = `
<input name="email" type="email" required autocomplete="email">
<input name="pin" inputmode="numeric" pattern="[0-9]{6}" autocomplete="postal-code">`;
const [email, pin] = form.elements;
email.value = "asha@";
pin.value = "4110";
console.log(email.validity.typeMismatch, pin.validity.patternMismatch, form.checkValidity());
pin.setCustomValidity("Enter the 6-digit PIN code");
console.log(pin.validationMessage);
email.value = "asha@example.in";
pin.value = "411001";
pin.setCustomValidity("");
console.log(form.checkValidity(), Object.fromEntries(new FormData(form)));Output (verified)
true true false
Enter the 6-digit PIN code
true { email: 'asha@example.in', pin: '411001' }FormData collects every named field, ready to send with fetch.
State
- email.validity.typeMismatch = true
- pin.validity.patternMismatch = true
Page
empty
The user types "asha@" in email and "4110" in PIN code. The browser checks the attributes on every change.
Read the steps as text
- The user types "asha@" in email and "4110" in PIN code. The browser checks the attributes on every change.
- On submit, your code reads validity and calls setCustomValidity with a clear message for the PIN field.
- reportValidity() shows the message next to the first invalid field and moves focus there.
- Fixed values, custom message cleared with setCustomValidity(""): the form is valid, and FormData collects it.
Predict#
Predict first
You call input.setCustomValidity('Too short') and never call it again. The user fixes the value. Is the field valid?
Any non-empty custom message makes the field invalid, whatever its value. You must call setCustomValidity("") when the input is fixed. Forgetting this traps users on a form they cannot submit.
Interview angle#
Say it like this — about 30 seconds
“I start with HTML validation attributes, then use the Constraint Validation API for better messages: check input.validity, set a specific message with setCustomValidity, and show it with reportValidity, or render my own error text linked with aria-describedby. I clear the custom message when the value changes. For filling, I set autocomplete tokens such as email, tel and postal-code, and on mobile I use inputmode for the right keyboard and enterkeyhint for the Enter key’s label. :user-invalid styles errors only after the user interacts.”
Follow-up How do you show custom validation messages on a form?
validity, call setCustomValidity(message), then reportValidity(), or show your own text linked with aria-describedby and aria-invalid.Follow-up What are inputmode and autocomplete used for?
Follow-up Why not type="number" for a PIN code or card number?
inputmode="numeric" with a pattern.Practice#
Guided
Write accessible validation for a three-field sign-up form: clear messages, aria-invalid, and visible error text.
Done when
- Each invalid field gets the right message,
aria-invalid="true"and its error text. - Fixed fields are cleared: no custom message, no
aria-invalid, empty error text. - The function returns whether the whole form is valid.
Remember#
Try to answer each card before you open it. Then add them to your reviews.
What does setCustomValidity("message") do?
Marks the field invalid with your message, until you call it with "".
Which property tells you why a field is invalid?
input.validity (valueMissing, typeMismatch, patternMismatch, …).
What does inputmode="numeric" do?
Shows a number keyboard on mobile without number-input quirks.
Why use :user-invalid instead of :invalid?
It applies only after the user has interacted, so empty forms are not red at load.
Go deeper
Four layers. Stop at the one your interview needs; each ends with a quick check.
The core ideaEvery round
email, tel, postal-code or one-time-code tells the browser what a field is. Correct tokens can cut form-filling time sharply, and one-time-code lets phones fill SMS codes Source: HTML Standard: Autofill.Check yourself: Name three autocomplete tokens for a delivery form.
For example name, tel, postal-code, street-address, email.
How it works underneathSenior rounds
inputmode (numeric, decimal, tel, email, search, url) picks the keyboard without changing validation. enterkeyhint (next, go, search, send, done) labels the Enter key.Check yourself: Which keyboard does inputmode="decimal" show?
Numbers with a decimal separator.
Edge cases and trapsWhere people slip
static formAssociated = true and ElementInternals, which gives them setFormValue and their own validity (WEB.19).novalidate only if you show errors yourself.Check yourself: Can a custom element take part in a form?
Yes, with static formAssociated = true and ElementInternals.
In productionStaff-level answers
:user-invalid, so untouched fields are not red at load: Chrome 119, Firefox 88, Safari 16.5 Source: MDN: Constraint validation.aria-describedby so screen readers read it.Check yourself: Which pseudo-class styles errors only after interaction?
:user-invalid
Finished the five steps? Mark it, and its cards join your reviews.
Last checked 2026-11-01. Spot a mistake? Use “Report an error” below — fixes are listed on the corrections page.
Interview questions this answers
- How do you show custom validation messages on a form?
- What are
inputmodeandautocompleteused for?