Skip to content

Bootstrap Form Validation — Client-Side Validation Feedback

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Bootstrap Form Validation. We cover key concepts, practical examples, and best practices to help you master this topic.

Bootstrap form validation styles valid and invalid states with colored borders, icons, and feedback messages using CSS classes and the native Constraint Validation API.

What You'll Learn

You will learn how to add validation styles to forms, display valid and invalid feedback messages, use tooltip-style validation, and implement custom validation with JavaScript.

Why It Matters

Validation feedback guides users to correct errors. DodaTech's registration form uses Bootstrap validation to show green borders on valid fields and red borders with error messages on invalid fields.

Real-World Use

Durga Antivirus Pro's license key entry form uses custom Bootstrap validation to check key format in real-time, showing success or failure feedback as the user types.

flowchart LR
    A[Forms & Inputs] --> B[Form Validation]
    B --> C[Validation States]
    B --> D[Feedback Messages]
    B --> E[JavaScript Validation]
    B --> F[Tooltips]
    style B fill:#7952b3,stroke:#563d7c,color:#fff
    style E fill:#22c55e,stroke:#16a34a,color:#fff

Validation States

Bootstrap applies validation styles using was-validated class on the form:

<form class="was-validated">
  <div class="mb-3">
    <label for="validName" class="form-label">Name</label>
    <input type="text" class="form-control is-valid" id="validName" value="John Doe" required>
    <div class="valid-feedback">Looks good!</div>
  </div>
  <div class="mb-3">
    <label for="invalidEmail" class="form-label">Email</label>
    <input type="email" class="form-control is-invalid" id="invalidEmail" value="not-an-email" required>
    <div class="invalid-feedback">Please provide a valid email address.</div>
  </div>
</form>

Expected output: The name field has a green border with success feedback. The email field has a red border with error feedback.

Validation with Constraint Validation API

<form id="validationForm" novalidate>
  <div class="mb-3">
    <label for="name" class="form-label">Full Name</label>
    <input type="text" class="form-control" id="name" required minlength="2">
    <div class="valid-feedback">Name looks good.</div>
    <div class="invalid-feedback">Please enter a name (minimum 2 characters).</div>
  </div>
  <div class="mb-3">
    <label for="age" class="form-label">Age</label>
    <input type="number" class="form-control" id="age" min="18" max="120" required>
    <div class="valid-feedback">Valid age.</div>
    <div class="invalid-feedback">Age must be between 18 and 120.</div>
  </div>
  <div class="mb-3">
    <label class="form-label">Terms</label>
    <div class="form-check">
      <input class="form-check-input" type="checkbox" id="terms" required>
      <label class="form-check-label" for="terms">Agree to terms and conditions</label>
      <div class="invalid-feedback">You must agree before submitting.</div>
    </div>
  </div>
  <button class="btn btn-primary" type="submit">Submit</button>
</form>

<script>
  (function() {
    var form = document.getElementById('validationForm');
    form.addEventListener('submit', function(event) {
      if (!form.checkValidity()) {
        event.preventDefault();
        event.stopPropagation();
      }
      form.classList.add('was-validated');
    }, false);
  })();
</script>

Expected output: Clicking submit with empty or invalid fields shows red borders and error messages. Valid fields show green borders and success messages.

The novalidate attribute on the form disables the browser's default validation popups, letting Bootstrap's custom UI handle feedback.

Supported Elements

Validation works on all form controls:

<form class="was-validated">
  <div class="mb-3">
    <label for="selectValidation" class="form-label">Select</label>
    <select class="form-select" id="selectValidation" required>
      <option value="">Choose...</option>
      <option value="1">Option 1</option>
    </select>
    <div class="invalid-feedback">Please select an option.</div>
  </div>

  <div class="mb-3">
    <label for="textareaValidation" class="form-label">Message</label>
    <textarea class="form-control" id="textareaValidation" required minlength="10"></textarea>
    <div class="invalid-feedback">Message must be at least 10 characters.</div>
  </div>

  <div class="mb-3">
    <div class="form-check">
      <input type="radio" class="form-check-input" name="radioValidation" id="radio1" required>
      <label class="form-check-label" for="radio1">Option 1</label>
    </div>
    <div class="form-check">
      <input type="radio" class="form-check-input" name="radioValidation" id="radio2">
      <label class="form-check-label" for="radio2">Option 2</label>
    </div>
  </div>
</form>

Expected output: Validation states apply to select menus, textareas, checkboxes, and radio buttons.

Tooltip Validation

Display feedback as tooltips instead of block messages:

<form id="tooltipForm" novalidate>
  <div class="mb-3 position-relative">
    <label for="tooltipName" class="form-label">Username</label>
    <input type="text" class="form-control" id="tooltipName" required pattern="[a-zA-Z0-9]{3,}">
    <div class="valid-tooltip">Username is available.</div>
    <div class="invalid-tooltip">Username must be at least 3 alphanumeric characters.</div>
  </div>
  <button class="btn btn-primary" type="submit">Check</button>
</form>

<script>
  (function() {
    var form = document.getElementById('tooltipForm');
    form.addEventListener('submit', function(event) {
      if (!form.checkValidity()) {
        event.preventDefault();
        event.stopPropagation();
      }
      form.classList.add('was-validated');
    }, false);
  })();
</script>

Expected output: Validation feedback appears as small tooltip popups above the input fields instead of block text below.

Server-Side Validation

Mark fields as invalid from the server:

<div class="mb-3">
  <label for="email" class="form-label">Email</label>
  <input type="email" class="form-control is-invalid" id="email" value="existing@example.com">
  <div class="invalid-feedback">This email is already registered.</div>
</div>

Expected output: The email field shows red styling with a server-side error message without going through the client validation cycle.

Common Mistakes

1. Forgetting to Add novalidate to the Form

Without novalidate, the browser shows its own validation popups that conflict with Bootstrap's custom feedback.

2. Using is-valid/is-invalid Without was-validated

The is-valid and is-invalid classes need the was-validated class on the form (or needs-validation) to trigger their display.

3. Missing valid-feedback Elements

The feedback elements (valid-feedback or invalid-feedback) must exist in the DOM. Without them, no message appears even when the state is correct.

4. Not Preventing Form Submission

The JavaScript must call event.preventDefault() when validation fails. Otherwise the form submits despite invalid data.

5. Using Both Block and Tooltip Feedback

valid-feedback and valid-tooltip are different display modes. Using both on the same input causes layout issues.

Practice Questions

  1. What class styles a valid input with a green border? is-valid adds a green border to the input.

  2. How do you trigger Bootstrap's validation styles? Add the was-validated class to the <form> element after submission attempt.

  3. What HTML attribute disables browser default validation? novalidate on the form element disables native validation popups.

  4. How is tooltip validation different from block validation? Tooltip validation uses valid-tooltip/invalid-tooltip classes and appears as a floating popup. Block validation uses valid-feedback/invalid-feedback and appears below the input.

  5. Can you use Bootstrap validation with server-side errors? Yes. Add is-invalid class to the input and fill the invalid-feedback div with the server error message.

Challenge

Create a password setup form with fields for new password and confirm password. Use custom JavaScript validation that checks passwords match and meets minimum length requirements.

FAQ

Does Bootstrap validation work on all browsers?

Yes. Bootstrap uses the Constraint Validation API supported in all modern browsers. Feedback falls back to basic styling in older browsers.

Can I customize validation colors?

Yes. Override the $form-validation-states Sass map or set custom CSS for .is-valid and .is-invalid borders.

How do I validate a group of checkboxes?

Use a wrapper with role=group and aria-required. At least one checkbox must be checked. Custom JavaScript is typically needed for group validation.

Can I show real-time validation as the user types?

Yes. Listen to input or blur events and toggle is-valid/is-invalid classes based on the input's validity.

What is the difference between needs-validation and was-validated?

needs-validation is an alternative approach that uses :invalid pseudo-class. was-validated is the recommended approach with explicit class toggling.

Mini Project

Build a registration form with name, email, password, password confirmation, and terms checkbox. Implement full client-side validation with custom error messages. The password must be at least 8 characters with one number and one uppercase letter.

What's Next

Learn Bootstrap Buttons for button styling. Then explore Button Groups for grouped button layouts.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro