Form Validation
HTML validates simple rules on its own. JavaScript adds rules HTML can’t express — like “passwords must match” — and friendlier messages.
On this page · 5 min · Intermediate
On this page
- Learning objectives
- Explanation
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Intermediate
- Updated
- Oct 27, 2026
Related tutorials
Learning objectives#
- Use checkValidity and validationMessage
- Add custom rules with setCustomValidity
- Show errors near the field and focus it
- Remember that the server must validate too
Explanation#
Every input has a validity state built from HTML attributes such as required, type="email" and minlength.
form.checkValidity() returns true if every field is valid. input.validationMessage gives the browser’s message.
input.setCustomValidity('message') marks a field invalid with your own message; setCustomValidity('') clears it.
Client-side validation helps users; it is not security. Always validate again on the server.
Code example: Sign-up form with a password match#
<style>label{display:block;margin:8px 0} #msg{color:#b91c1c;font-weight:600}</style>
<form id="signup" novalidate>
<label>Email <input id="email" type="email" required></label>
<label>Password <input id="pw" type="password" required minlength="8"></label>
<label>Confirm <input id="pw2" type="password" required></label>
<button>Sign up</button>
<p id="msg" role="alert"></p>
</form>
<script>
const form = document.querySelector('#signup');
const msg = document.querySelector('#msg');
form.addEventListener('submit', (e) => {
e.preventDefault();
const pw = form.querySelector('#pw'), pw2 = form.querySelector('#pw2');
pw2.setCustomValidity(pw.value === pw2.value ? '' : 'Passwords do not match');
if (!form.checkValidity()) {
const firstBad = form.querySelector(':invalid');
msg.textContent = firstBad.validationMessage;
firstBad.focus();
return;
}
msg.style.color = '#15803d';
msg.textContent = '✓ All good — ready to send!';
});
</script>
Submitting shows the first problem (for example “Passwords do not match”) and focuses that field; a valid form shows a green success message.
Step-by-step explanation#
- novalidate turns off the browser’s pop-up bubbles so we can show our own message.
- The custom rule sets or clears an error on the confirm field.
- checkValidity checks every rule, built-in and custom.
- :invalid finds the first bad field so we can show its message and focus it.
Real-world use case#
Registration, checkout and contact forms combine HTML rules with a few JavaScript checks for a smooth experience.
Common mistakes#
If you do not call setCustomValidity('') when the value becomes valid, the field stays invalid forever.
Requests can be sent directly to your API. Validate on the server as well.
Best practices#
- Use HTML attributes first, JavaScript for extra rules
- Show errors next to the field and announce them (role="alert")
- Focus the first invalid field
- Validate again on the server
Remember this#
HTML rules first, JavaScript for the rest.
setCustomValidity('msg') = invalid; setCustomValidity('') = valid again.
Browser validation is for users; server validation is for security.
Practice exercise#
Your task: Add a rule that the email must end with "@example.com", with the message “Use your company email”.
Show solution
const email = form.querySelector('#email');
email.setCustomValidity(email.value.endsWith('@example.com') ? '' : 'Use your company email');
Mini quiz#
How do you mark a field valid again after a custom error?
Want more? Practise all JavaScript MCQs · JavaScript interview questions
My notes#
Saved in this browser.