How To Validate a Contact Form
Learn how to check a contact form before it is sent, and show friendly error messages next to each field.
Step 1: The HTML
Each field has a label and an empty <small> element for its error message. novalidate turns off the browser's own pop-ups, so we can show our own messages.
Example
<form id="contact" novalidate>
<label for="name">Name</label>
<input type="text" id="name">
<small class="error" id="nameErr"></small>
<label for="email">Email</label>
<input type="email" id="email">
<small class="error" id="emailErr"></small>
<button type="submit">Send</button>
</form>
<p id="result"></p>Step 2: The CSS
Errors are red. A field with a problem gets a red border through the invalid class.
Example
.error { color: #dc2626; display: block; min-height: 18px; }
input.invalid, textarea.invalid { border-color: #dc2626; }Step 3: The JavaScript
On submit, stop the page from reloading with preventDefault(), then check each field. If everything is fine, show a success message.
Example
document.getElementById("contact").addEventListener("submit", function (e) {
e.preventDefault();
let ok = true;
const name = document.getElementById("name");
if (name.value.trim().length < 3) {
showError(name, "nameErr", "Please enter your full name.");
ok = false;
} else {
clearError(name, "nameErr");
}
// ...check the other fields the same way...
if (ok) document.getElementById("result").innerHTML = "Thank you! We will contact you soon.";
});trim() removes spaces from both ends, so a name of only spaces does not pass.
The Rules We Check
| Field | Rule |
|---|---|
| Name | At least 3 letters |
| Looks like name@site.com | |
| Phone | 11 digits starting with 03 |
| Message | At least 10 characters |
The email and phone rules use regular expressions, short patterns that describe text. /^03\d{9}$/ means "starts with 03, then exactly 9 more digits, then ends".
The Complete Example
Example
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 20px; max-width: 420px; }
label { display: block; margin-top: 10px; font-weight: bold; }
input, textarea { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 6px; font-size: 15px; box-sizing: border-box; }
input.invalid, textarea.invalid { border-color: #dc2626; }
.error { color: #dc2626; display: block; min-height: 18px; font-size: 13px; }
button { margin-top: 12px; background: #059669; color: white; border: none; padding: 10px 18px; border-radius: 6px; font-size: 16px; cursor: pointer; }
#result { color: #059669; font-weight: bold; }
</style>
</head>
<body>
<h2>Contact Us</h2>
<form id="contact" novalidate>
<label for="name">Name</label>
<input type="text" id="name">
<small class="error" id="nameErr"></small>
<label for="email">Email</label>
<input type="email" id="email">
<small class="error" id="emailErr"></small>
<label for="phone">Mobile number</label>
<input type="tel" id="phone" placeholder="03001234567">
<small class="error" id="phoneErr"></small>
<label for="msg">Message</label>
<textarea id="msg" rows="4"></textarea>
<small class="error" id="msgErr"></small>
<button type="submit">Send</button>
</form>
<p id="result"></p>
<script>
function showError(field, errId, text) {
field.classList.add("invalid");
document.getElementById(errId).innerHTML = text;
}
function clearError(field, errId) {
field.classList.remove("invalid");
document.getElementById(errId).innerHTML = "";
}
function check(id, errId, test, text) {
const field = document.getElementById(id);
if (test(field.value.trim())) { clearError(field, errId); return true; }
showError(field, errId, text);
return false;
}
document.getElementById("contact").addEventListener("submit", function (e) {
e.preventDefault();
const results = [
check("name", "nameErr", function (v) { return v.length >= 3; }, "Please enter your full name."),
check("email", "emailErr", function (v) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v); }, "Please enter a valid email."),
check("phone", "phoneErr", function (v) { return /^03\d{9}$/.test(v); }, "Use 11 digits starting with 03."),
check("msg", "msgErr", function (v) { return v.length >= 10; }, "Message must be at least 10 characters.")
];
const result = document.getElementById("result");
if (results.every(Boolean)) {
result.innerHTML = "Thank you! We will contact you soon.";
this.reset();
} else {
result.innerHTML = "";
}
});
</script>
</body>
</html>Try it Yourself »Name: "Al" -> Please enter your full name. Mobile: "0300123" -> Use 11 digits starting with 03. All fields correct -> Thank you! We will contact you soon.
All four checks run every time, so the visitor sees every problem at once instead of one by one.
JavaScript checks make forms friendlier, but they can be switched off. The server that receives the form must always check the data again.
Exercise
Exercise
Why does the script call e.preventDefault() in the submit handler?
