reportValidity and setCustomValidity
Trigger browser validation UI and set custom error messages.
reportValidity and setCustomValidity is a free HTML Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the HTML Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Two APIs for Built-in UX
The Constraint Validation API exposes two methods that drive the browser's built-in validation UI: reportValidity (show the tooltip) and setCustomValidity (provide a custom error message). Together they let you customize messages while keeping the native presentation.
reportValidity vs checkValidity
checkValidity() silently returns true/false — no UI side effects. reportValidity() does the same check but additionally focuses the first invalid field and shows the browser's validation tooltip. Choose reportValidity when you want native UX for free.
document.forms.signup.addEventListener("submit", (e) => {
if (!e.target.reportValidity()) {
e.preventDefault();
// browser already focused first invalid field and showed tooltip
}
});Programmatic Validation
For multi-step wizards, validate each step's fields before advancing: if (step.reportValidity()) { next(); }. The browser handles the error display and the user is focused on the field that needs attention — saving you from reimplementing focus management.
setCustomValidity Overrides Messages
Default messages ("Please fill out this field") may not match your tone. input.setCustomValidity("Username is required") replaces the default with your text. The input is treated as invalid until you clear the message.
Clearing Custom Messages
input.setCustomValidity("") removes the custom message and re-enables normal validation. Call this whenever you re-validate, otherwise stale custom messages remain even after the user fixes the issue.
input.addEventListener("input", () => {
if (input.value.length < 3) {
input.setCustomValidity("Must be at least 3 characters");
} else {
input.setCustomValidity("");
}
});Async Validation
For server-side checks (username uniqueness, coupon validity), use setCustomValidity after the async response: const ok = await checkUsername(value); input.setCustomValidity(ok ? "" : "Already taken");. The browser picks up the new validity state immediately.
Pairing with Custom Error UI
To use your own error display while still getting the validity tracking, listen to the invalid event and call e.preventDefault() to suppress the native tooltip: input.addEventListener("invalid", (e) => { e.preventDefault(); showError(input, input.validationMessage); }).
Multiple Custom Constraints
setCustomValidity supports only one custom message at a time. To enforce several rules, check each and call setCustomValidity with the most relevant message in priority order. The first failing rule is the one displayed.
Don't Overlap with Built-in
If you set a custom message for an empty required field, both your message and the default may conflict. Pick one approach per field: either disable the built-in constraint (use type="text" instead of type="email" and validate via setCustomValidity), or trust the built-in entirely.
Form-Level Custom Validation
For cross-field validation (password confirmation matching), apply setCustomValidity to the related field: confirmInput.setCustomValidity(confirmInput.value === passInput.value ? "" : "Passwords do not match"). The form is invalid until both match.
Internationalization
Built-in messages are localized by the browser based on user language. Custom messages set via setCustomValidity must be in the right language yourself — read navigator.language or your own i18n state and supply the matching translation.
Testing
Open DevTools and try every invalid path: empty submit, partial input, format mismatch, async failure. Verify that the correct message shows, that fixing the issue clears it, and that submitting a valid form proceeds. Edge cases (paste of invalid format, browser autofill) deserve specific tests.
Knowledge Check
After calling input.setCustomValidity("Already taken"), how do you tell the browser the input is valid again?
Summary
reportValidity triggers the browser's built-in validation UI (focus + tooltip), perfect for programmatic checks. setCustomValidity overrides default messages with your text — clear with empty string when valid again. Listen to the invalid event with preventDefault for entirely custom error displays. Use for cross-field validation, async checks, and localized custom messages.
Frequently asked questions
Is the “reportValidity and setCustomValidity” lesson free?
Yes — the full text of “reportValidity and setCustomValidity” is free to read here on the web, and the HTML Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the HTML Academy course, upgrade to CoddyKit PRO.
What will I learn in “reportValidity and setCustomValidity”?
Trigger browser validation UI and set custom error messages. You practise HTML Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start HTML Academy?
No prior experience is required. HTML Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “reportValidity and setCustomValidity” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this HTML Academy lesson?
Yes. Every HTML Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The FormData API
- The Constraint Validation API
- reportValidity and setCustomValidity
- Form Reset Events and State Management