Bootstrap - Bootstrap 5 Form Validation

Bootstrap 5 comes with a built-in, fully client-side form validation system that leverages HTML5 form validation and adds custom styling for valid and invalid inputs. It’s easy to implement and works for text inputs, selects, checkboxes, radios, and more.


1. Basics of Bootstrap 5 Form Validation

To enable Bootstrap validation:

  1. Add the class .needs-validation to your <form>.

  2. Use novalidate to disable default browser validation messages.

  3. Add the required attribute to inputs.

  4. Use .valid-feedback and .invalid-feedback to display messages.

Example: Basic Validation

<form class="needs-validation" novalidate>
  <div class="mb-3">
    <label for="username" class="form-label">Username</label>
    <input type="text" class="form-control" id="username" placeholder="Username" required>
    <div class="valid-feedback">
      Looks good!
    </div>
    <div class="invalid-feedback">
      Please enter a username.
    </div>
  </div>
  <div class="mb-3">
    <label for="email" class="form-label">Email</label>
    <input type="email" class="form-control" id="email" placeholder="Email" required>
    <div class="valid-feedback">
      Valid email!
    </div>
    <div class="invalid-feedback">
      Please enter a valid email.
    </div>
  </div>
  <button class="btn btn-primary" type="submit">Submit</button>
</form>

2. How Validation Works

  • Invalid input: .is-invalid is added automatically.

  • Valid input: .is-valid is added automatically.

  • You can customize feedback messages using .invalid-feedback and .valid-feedback.


3. Custom Validation with JavaScript

Bootstrap recommends the following JS snippet to prevent form submission if invalid:

<script>
(() => {
  'use strict'
  
  const forms = document.querySelectorAll('.needs-validation')

  Array.from(forms).forEach(form => {
    form.addEventListener('submit', event => {
      if (!form.checkValidity()) {
        event.preventDefault()
        event.stopPropagation()
      }
      form.classList.add('was-validated')
    }, false)
  })
})()
</script>

Explanation:

  • form.checkValidity() → Checks HTML5 constraints.

  • .was-validated → Triggers Bootstrap styling.

  • Prevents form submission when invalid.


4. Validating Different Input Types

a) Text

<input type="text" class="form-control" required>
<div class="invalid-feedback">This field is required.</div>

b) Email

<input type="email" class="form-control" required>
<div class="invalid-feedback">Enter a valid email.</div>

c) Password

<input type="password" class="form-control" required minlength="6">
<div class="invalid-feedback">Password must be at least 6 characters.</div>

d) URL / Number / Date

<input type="url" class="form-control" required>
<input type="number" class="form-control" min="1" max="100" required>
<input type="date" class="form-control" required>

5. Checkbox & Radio Validation

  • Add required to at least one checkbox or radio in a group.

  • Use .invalid-feedback to show a message.

Checkbox Example

<div class="form-check mb-3">
  <input class="form-check-input" type="checkbox" value="" id="terms" required>
  <label class="form-check-label" for="terms">
    Accept terms and conditions
  </label>
  <div class="invalid-feedback">
    You must agree before submitting.
  </div>
</div>

Radio Example

<div class="form-check">
  <input class="form-check-input" type="radio" name="gender" id="male" value="male" required>
  <label class="form-check-label" for="male">Male</label>
</div>
<div class="form-check">
  <input class="form-check-input" type="radio" name="gender" id="female" value="female">
  <label class="form-check-label" for="female">Female</label>
  <div class="invalid-feedback">
    Please select a gender.
  </div>
</div>

6. Select and Floating Label Validation

Select

<div class="form-floating mb-3">
  <select class="form-select" id="floatingSelect" required>
    <option value="">Choose...</option>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
  </select>
  <label for="floatingSelect">Select an option</label>
  <div class="invalid-feedback">Please select a valid option.</div>
</div>

Floating Labels

Floating labels work seamlessly with validation—just include .invalid-feedback.


7. Tooltips for Validation

Bootstrap 5 allows you to use tooltips instead of messages.

<form class="needs-validation" novalidate>
  <div class="mb-3 position-relative">
    <input type="text" class="form-control" placeholder="Username" required>
    <div class="invalid-tooltip">
      Username is required.
    </div>
  </div>
  <button class="btn btn-primary" type="submit">Submit</button>
</form>
  • .invalid-tooltip appears as a tooltip rather than below the input.

  • Useful for compact forms.


8. Full Example: Bootstrap 5 Form Validation

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 5 Form Validation</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="p-4">

<h3>Bootstrap 5 Form Validation</h3>

<form class="needs-validation" novalidate>
  <div class="mb-3">
    <label for="username" class="form-label">Username</label>
    <input type="text" class="form-control" id="username" placeholder="Username" required>
    <div class="invalid-feedback">Please enter a username.</div>
  </div>

  <div class="mb-3">
    <label for="email" class="form-label">Email</label>
    <input type="email" class="form-control" id="email" placeholder="Email" required>
    <div class="invalid-feedback">Please enter a valid email.</div>
  </div>

  <div class="mb-3">
    <label for="password" class="form-label">Password</label>
    <input type="password" class="form-control" id="password" placeholder="Password" required minlength="6">
    <div class="invalid-feedback">Password must be at least 6 characters.</div>
  </div>

  <div class="form-check mb-3">
    <input class="form-check-input" type="checkbox" value="" id="terms" required>
    <label class="form-check-label" for="terms">Accept terms</label>
    <div class="invalid-feedback">You must agree before submitting.</div>
  </div>

  <button class="btn btn-primary" type="submit">Submit</button>
</form>

<script>
(() => {
  'use strict'
  const forms = document.querySelectorAll('.needs-validation')
  Array.from(forms).forEach(form => {
    form.addEventListener('submit', event => {
      if (!form.checkValidity()) {
        event.preventDefault()
        event.stopPropagation()
      }
      form.classList.add('was-validated')
    }, false)
  })
})()
</script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>