Bootstrap Form Validation
Validation tells users when they got a field right or wrong, using clear green and red styles. Bootstrap 5 ships two flavours: instant feedback powered by the browser, and custom feedback you control with a little JavaScript. Both use the same friendly colours and messages.
Valid and invalid states
The core idea is two feedback classes. Add .is-valid to a field to turn it green, or .is-invalid to turn it red. Alongside the field, add a message using .valid-feedback (green) or .invalid-feedback (red). The message only appears when the field carries the matching state class.
Showing feedback messages
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="mb-3">
<label for="user" class="form-label">Username</label>
<input type="text" class="form-control is-invalid" id="user">
<div class="invalid-feedback">Please choose a username.</div>
</div>
<div class="mb-3">
<label for="code" class="form-label">Referral code</label>
<input type="text" class="form-control is-valid" id="code" value="HYR2026">
<div class="valid-feedback">Looks good!</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>Browser validation with .was-validated
For automatic checking, add the required attribute to your fields and the novalidate attribute to the <form>. A small script adds the class .was-validated when the user submits. Bootstrap then colours every field based on whether it passed the browser's built-in rules.
A self-validating form
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<form class="needs-validation" novalidate>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" required>
<div class="invalid-feedback">Enter a valid email.</div>
</div>
<button class="btn btn-primary" type="submit">Submit</button>
</form>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>The script that triggers validation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.querySelectorAll('.needs-validation').forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
});
});
</script>
</body>
</html>Validation classes
- Use .is-valid and .is-invalid for manual, field-by-field feedback.
- Use required plus .was-validated for automatic browser checking.
- Feedback messages need the matching state class to appear.
- Always re-check submitted data on the server for security.