Forms and Form Validation
1. Introduction
(1) Prerequisites
- Lesson 12: Tables
(2) 🎯 What You'll Learn
- Style controls using
form-control,form-select,form-check-input - Layout forms using grid and inline layouts
- Add prefix/suffix elements using
input-group - Implement client-side validation using
needs-validation - Implement floating labels using
form-floating
(3) The Pain Point
Bob is developing a user registration page and needs to collect name, email, password, country selection, and terms agreement—Bootstrap's form classes let him skip writing any CSS styles, focusing solely on the HTML structure and validation logic.
(4) The Solution
Forms are the core way to interact with users. Bootstrap provides a unified set of form control styles and a validation feedback system, making form development efficient and aesthetically pleasing.
How to understand it: Bootstrap forms = a beauty filter for native browser controls—all
<input>,<select>,<textarea>elements get unified styles, spacing, and interactive feedback when wrapped with.form-control.
(5) The Benefit
Using Bootstrap's form utility classes, you can focus on HTML structure and validation logic without writing any CSS style code.
2. Form Controls
All text-based input controls use .form-control:
▶ Example: Basic Form
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Demo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-4">
<form>
<div class="mb-3">
<label for="name" class="form-label">Full Name</label>
<input type="text" class="form-control" id="name" placeholder="Enter your name">
</div>
<div class="mb-3">
<label for="country" class="form-label">Country</label>
<select class="form-select" id="country">
<option selected>Choose...</option>
<option value="us">United States</option>
<option value="jp">Japan</option>
<option value="uk">United Kingdom</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">Skills</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="html" checked>
<label class="form-check-label" for="html">HTML</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="css">
<label class="form-check-label" for="css">CSS</label>
</div>
</div>
<div class="mb-3">
<label class="form-label">Experience Level</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="level" id="beginner" checked>
<label class="form-check-label" for="beginner">Beginner</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="level" id="advanced">
<label class="form-check-label" for="advanced">Advanced</label>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</body>
</html>
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
3. Form Control Types
| Control | Class | Description |
|---|---|---|
| Text input | form-control |
Single-line text, email, password, url, etc. |
| Textarea | form-control |
Multi-line text (rows control the number of lines) |
| Select | form-select |
Dropdown select box |
| Checkbox | form-check-input |
Multiple selection |
| Radio | form-check-input |
Single selection (mutually exclusive with the same name) |
| Range | form-range |
Slider |
| File | form-control |
File upload |
4. Form Layout
(1) Grid Layout
<div class="row">
<div class="col-md-6 mb-3">
<label for="firstName" class="form-label">First Name</label>
<input type="text" class="form-control" id="firstName">
</div>
<div class="col-md-6 mb-3">
<label for="lastName" class="form-label">Last Name</label>
<input type="text" class="form-control" id="lastName">
</div>
</div>
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
(2) Inline Form
<form class="row g-3">
<div class="col-auto">
<input type="search" class="form-control" placeholder="Search...">
</div>
<div class="col-auto">
<button class="btn btn-primary" type="submit">Go</button>
</div>
</form>
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
(3) Horizontal Form
<div class="row mb-3">
<label for="email2" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="email2">
</div>
</div>
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
5. Input Groups
<div class="input-group mb-3">
<span class="input-group-text">@</span>
<input type="text" class="form-control" placeholder="Username">
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Amount">
<span class="input-group-text">.00</span>
</div>
<div class="input-group mb-3">
<button class="btn btn-outline-secondary" type="button">Search</button>
<input type="text" class="form-control" placeholder="Type to search">
</div>
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
6. Form Validation
<form class="row g-3 needs-validation" novalidate>
<div class="col-md-4">
<label for="validationName" class="form-label">First Name</label>
<input type="text" class="form-control" id="validationName" required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Please enter your name.</div>
</div>
<div class="col-md-4">
<label for="validationEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="validationEmail" required>
<div class="valid-feedback">Valid email!</div>
<div class="invalid-feedback">Please provide a valid email.</div>
</div>
<div class="col-12">
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</form>
<script>
(function() {
var forms = document.querySelectorAll('.needs-validation')
Array.prototype.slice.call(forms).forEach(function(form) {
form.addEventListener('submit', function(event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
(1) Validation Feedback Styles
| Class | Condition | Display Method |
|---|---|---|
.valid-feedback |
Input is valid | Green text |
.invalid-feedback |
Input is invalid | Red text |
.was-validated |
After form submission | Triggers all feedback |
is-valid / is-invalid |
Manual control | Status border |
7. More Form Examples
▶ Example: Complete Registration Form (with Validation)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Signup Form</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-4">
<div class="card mx-auto" style="max-width: 500px;">
<div class="card-header bg-primary text-white">
<h4 class="mb-0">Create Account</h4>
</div>
<div class="card-body">
<form class="needs-validation" novalidate>
<div class="mb-3">
<label for="fullName" class="form-label">Full Name</label>
<input type="text" class="form-control" id="fullName" required>
<div class="invalid-feedback">Please enter your name.</div>
</div>
<div class="mb-3">
<label for="signupEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="signupEmail" required>
<div class="invalid-feedback">Please enter a valid email.</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" minlength="8" required>
<div class="invalid-feedback">Password must be at least 8 characters.</div>
</div>
<div class="col-md-6">
<label for="confirmPwd" class="form-label">Confirm</label>
<input type="password" class="form-control" id="confirmPwd" required>
<div class="invalid-feedback">Passwords must match.</div>
</div>
</div>
<div class="mb-3">
<label for="countrySelect" class="form-label">Country</label>
<select class="form-select" id="countrySelect" required>
<option value="">Choose...</option>
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="jp">Japan</option>
</select>
<div class="invalid-feedback">Please select a country.</div>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="agreeTerms" required>
<label class="form-check-label" for="agreeTerms">I agree to the terms and conditions</label>
<div class="invalid-feedback">You must agree to continue.</div>
</div>
<button type="submit" class="btn btn-primary w-100">Register</button>
</form>
</div>
</div>
</div>
<script>
(function() {
var forms = document.querySelectorAll('.needs-validation')
Array.prototype.slice.call(forms).forEach(function(form) {
form.addEventListener('submit', function(event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>
</body>
</html>
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
▶ Example: Search Form (Input Group)
<form class="container py-4">
<div class="row g-2">
<div class="col-md-3">
<select class="form-select">
<option selected>All Categories</option>
<option value="electronics">Electronics</option>
<option value="clothing">Clothing</option>
<option value="books">Books</option>
</select>
</div>
<div class="col-md-6">
<div class="input-group">
<input type="search" class="form-control" placeholder="Search products...">
<button class="btn btn-primary" type="submit">Search</button>
</div>
</div>
<div class="col-md-3">
<button class="btn btn-outline-secondary w-100" type="button">Advanced Filters</button>
</div>
</div>
</form>
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
▶ Example: Inline Form
<form class="row row-cols-lg-auto g-3 align-items-center">
<div class="col-12">
<input type="text" class="form-control" placeholder="Username">
</div>
<div class="col-12">
<input type="password" class="form-control" placeholder="Password">
</div>
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="rememberMe">
<label class="form-check-label" for="rememberMe">Remember me</label>
</div>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">Sign In</button>
</div>
</form>
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
▶ Example: Floating Label Form
<div class="container py-4" style="max-width: 400px;">
<form>
<div class="form-floating mb-3">
<input type="email" class="form-control" id="floatingEmail" placeholder="name@example.com">
<label for="floatingEmail">Email address</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control" id="floatingPassword" placeholder="Password">
<label for="floatingPassword">Password</label>
</div>
<div class="form-floating mb-3">
<select class="form-select" id="floatingSelect">
<option value="">Choose...</option>
<option value="free">Free Plan</option>
<option value="pro">Pro Plan</option>
<option value="enterprise">Enterprise</option>
</select>
<label for="floatingSelect">Subscription Plan</label>
</div>
<div class="form-floating mb-3">
<textarea class="form-control" id="floatingTextarea" style="height: 100px" placeholder="Comments"></textarea>
<label for="floatingTextarea">Message</label>
</div>
<button class="btn btn-primary w-100">Submit</button>
</form>
</div>
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
(1) Form Layout Decision Flow
flowchart TD
A[Start designing form] --> B{Number of fields}
B -->|1-3| C[Simple stacking<br/>separate with mb-3]
B -->|4-8| D{Needs grouping?}
D -->|Yes| E[Grid layout<br/>row + col-*]
D -->|No| F[Inline/Horizontal layout]
B -->|8+| G[Multi-column grid<br/>or step-by-step]
E --> H{Needs prefix?}
H -->|Yes| I[input-group]
H -->|No| J[Direct form-control]
F --> K{Floating label?}
K -->|Yes| L[form-floating]
K -->|No| M[Regular label]
Output: The effect of Bootstrap 5.3 styled components (e.g., buttons, cards, carousel, collapse, etc.). The page uses the default Bootstrap theme (light) and responsive grid.
| Form Control | Class | Applicable Data Types |
|---|---|---|
| Single-line text | form-control |
Name, email, password |
| Multi-line text | form-control (textarea) |
Comments, descriptions |
| Dropdown select | form-select |
Country, category, options |
| Checkbox | form-check-input |
Multiple selection, terms agreement |
| Radio button | form-check-input (radio) |
Gender, level, options |
| Slider | form-range |
Price range, rating |
| File upload | form-control (file) |
Images, documents |
| Input Group Variant | Code Pattern | Use Case |
|---|---|---|
| Prefix text | input-group-text + form-control |
Amount $, username @ prefix |
| Suffix text | form-control + input-group-text |
Suffix .00, unit px |
| Prefix button | button + form-control |
Search box |
| Suffix button | form-control + button |
Password visibility toggle |
| Multiple elements | Multiple input-group-text |
Date range, combined input |
| Validation State | Class | Border | Feedback Text |
|---|---|---|---|
| Valid | is-valid |
Green | valid-feedback |
| Invalid | is-invalid |
Red | invalid-feedback |
| After submission | was-validated |
Auto-switches | Triggers all feedback |
| Tooltip | Combined with valid-tooltip |
Same as above | Bubble-style tip |
❓ Frequently Asked Questions
.form-control has width: 100% by default. To control width, place it inside a grid column (col-*) or add style="width: 300px"..form-label?margin-bottom: 0.5rem) and font size of <label>. It works without it, but adding it is recommended for consistency.<div class="invalid-feedback"> can be anything you want. Additionally, the setCustomValidity() method is supported.input-group can contain multiple input-group-text, form-control, and buttons.:placeholder-shown pseudo-class, which is supported by modern browsers. IE does not support it, but IE has ceased maintenance. If you need to support very old browsers, it's recommended to use traditional label layouts.📖 Summary
- Use
form-controlfor text controls,form-selectfor dropdowns,form-check-inputfor checkboxes/radios - Use
mb-3to separate form groups, and gridrow+col-*for multi-column layouts - Use
input-groupto add text/buttons before or after an input field - Form validation:
needs-validation+ JS +was-validated+valid-feedback/invalid-feedback
📝 Assignments
- ⭐ Create a complete registration form: name (text), age (number), country (select), password (password), confirm password, all using Bootstrap styles.
- ⭐⭐ Implement validation for the form in Assignment 1: name is required, 2-20 characters; password must be at least 8 characters; email must be in the correct format. Display a red
invalid-feedbackwhen conditions are not met. - ⭐⭐⭐ Create a search input group: a
form-selecton the left for category selection + aform-controlsearch box in the middle + a Search button on the right.
Previous Lesson: Tables · Next Lesson: Carousel and Modal



