HTML Form Validation
Built-in HTML5 Validation
HTML5 provides built-in form validation — no JavaScript needed for basic checks. The browser validates fields when the user submits the form and shows error messages automatically.
Validation Attributes
<form action="/submit" method="POST">
<!-- required: field must not be empty -->
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
<!-- minlength / maxlength: character count limits -->
<label for="username">Username (3-20 chars):</label>
<input type="text" id="username" name="username"
minlength="3" maxlength="20" required>
<!-- min / max: numeric range -->
<label for="age">Age (18-100):</label>
<input type="number" id="age" name="age" min="18" max="100" required>
<!-- type="email": validates email format -->
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<!-- type="url": validates URL format -->
<label for="website">Website:</label>
<input type="url" id="website" name="website"
placeholder="https://example.com">
<!-- pattern: custom regex validation -->
<label for="phone">Phone (10 digits):</label>
<input type="tel" id="phone" name="phone"
pattern="[0-9]{10}"
title="Please enter exactly 10 digits">
<!-- pattern: password strength -->
<label for="password">Password:</label>
<input type="password" id="password" name="password"
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
title="Must contain at least 8 characters, one uppercase, one lowercase, one number"
required>
<!-- step: numeric step value -->
<label for="price">Price (multiples of 0.50):</label>
<input type="number" id="price" name="price"
min="0" step="0.50">
<button type="submit">Submit</button>
</form>
Validation Attributes Reference
| Attribute | Description | Works on |
|---|---|---|
required | Field must not be empty | All inputs |
minlength | Minimum number of characters | text, password, textarea |
maxlength | Maximum number of characters | text, password, textarea |
min | Minimum value | number, date, range |
max | Maximum value | number, date, range |
step | Legal number intervals | number, range, date |
pattern | Regex pattern the value must match | text, tel, email, url |
title | Custom error message shown when pattern fails | All inputs |
type="email" | Validates email format automatically | input |
type="url" | Validates URL format automatically | input |
novalidate | Disables all validation on the form | form |
CSS Validation Styling
Use CSS pseudo-classes to style valid and invalid fields:
/* Valid input — green border */
input:valid {
border: 2px solid #27ae60;
outline-color: #27ae60;
}
/* Invalid input — red border */
input:invalid {
border: 2px solid #e74c3c;
outline-color: #e74c3c;
}
/* Only show invalid style after user has interacted */
input:not(:placeholder-shown):invalid {
border: 2px solid #e74c3c;
}
/* Required field indicator */
input:required {
border-left: 4px solid #f39c12;
}
<form>
<input type="email" placeholder="Enter email" required>
<!-- Green border when valid, red when invalid -->
<button type="submit">Submit</button>
</form>
JavaScript Validation (Custom Messages)
const emailInput = document.getElementById('email');
emailInput.addEventListener('invalid', () => {
if (emailInput.validity.valueMissing) {
emailInput.setCustomValidity('Please enter your email address.');
} else if (emailInput.validity.typeMismatch) {
emailInput.setCustomValidity('Please enter a valid email like: name@example.com');
} else {
emailInput.setCustomValidity('');
}
});
// Clear custom message when user starts typing
emailInput.addEventListener('input', () => {
emailInput.setCustomValidity('');
});