Bootstrap 5 Forms Tutorial

Responsive, accessible, and modern forms with Bootstrap utility and component classes.

What are Bootstrap Forms?

Bootstrap provides a comprehensive set of classes and components for building beautiful, responsive, and accessible forms. It includes styling for all standard HTML form elements, custom form controls, validation states, and layout utilities.

1. Basic Form Controls

Text Inputs
<!-- Basic text input -->
<div class="mb-3">
  <label for="textInput" class="form-label">Text Input</label>
  <input type="text" class="form-control" id="textInput" placeholder="Enter text">
</div>

<!-- Email input -->
<div class="mb-3">
  <label for="emailInput" class="form-label">Email address</label>
  <input type="email" class="form-control" id="emailInput" placeholder="name@example.com">
</div>

<!-- Password input -->
<div class="mb-3">
  <label for="passwordInput" class="form-label">Password</label>
  <input type="password" class="form-control" id="passwordInput" placeholder="Password">
</div>

<!-- Number input -->
<div class="mb-3">
  <label for="numberInput" class="form-label">Number</label>
  <input type="number" class="form-control" id="numberInput" placeholder="Quantity">
</div>

<!-- Telephone input -->
<div class="mb-3">
  <label for="telInput" class="form-label">Telephone</label>
  <input type="tel" class="form-control" id="telInput" placeholder="(555) 555-5555">
</div>

<!-- URL input -->
<div class="mb-3">
  <label for="urlInput" class="form-label">Website URL</label>
  <input type="url" class="form-control" id="urlInput" placeholder="https://example.com">
</div>

<!-- Date input -->
<div class="mb-3">
  <label for="dateInput" class="form-label">Date</label>
  <input type="date" class="form-control" id="dateInput">
</div>

<!-- Time input -->
<div class="mb-3">
  <label for="timeInput" class="form-label">Time</label>
  <input type="time" class="form-control" id="timeInput">
</div>

<!-- DateTime local input -->
<div class="mb-3">
  <label for="datetimeInput" class="form-label">Date & Time</label>
  <input type="datetime-local" class="form-control" id="datetimeInput">
</div>

<!-- Month input -->
<div class="mb-3">
  <label for="monthInput" class="form-label">Month</label>
  <input type="month" class="form-control" id="monthInput">
</div>

<!-- Week input -->
<div class="mb-3">
  <label for="weekInput" class="form-label">Week</label>
  <input type="week" class="form-control" id="weekInput">
</div>

<!-- Color picker -->
<div class="mb-3">
  <label for="colorInput" class="form-label">Color picker</label>
  <input type="color" class="form-control form-control-color" id="colorInput" value="#0d6efd">
</div>

<!-- Range slider -->
<div class="mb-3">
  <label for="rangeInput" class="form-label">Range slider</label>
  <input type="range" class="form-range" id="rangeInput">
</div>

<!-- Disabled input -->
<div class="mb-3">
  <label for="disabledInput" class="form-label">Disabled input</label>
  <input type="text" class="form-control" id="disabledInput" placeholder="Disabled input" disabled>
</div>

<!-- Readonly input -->
<div class="mb-3">
  <label for="readonlyInput" class="form-label">Readonly input</label>
  <input type="text" class="form-control" id="readonlyInput" value="This is readonly" readonly>
</div>

<!-- Plain text -->
<div class="mb-3">
  <label for="plainText" class="form-label">Plain text</label>
  <input type="text" readonly class="form-control-plaintext" id="plainText" value="email@example.com">
</div>
Textareas
<!-- Basic textarea -->
<div class="mb-3">
  <label for="textarea" class="form-label">Textarea</label>
  <textarea class="form-control" id="textarea" rows="3" placeholder="Enter your message here..."></textarea>
</div>

<!-- Textarea with custom rows -->
<div class="mb-3">
  <label for="textareaLarge" class="form-label">Large textarea</label>
  <textarea class="form-control" id="textareaLarge" rows="5"></textarea>
</div>

<!-- Disabled textarea -->
<div class="mb-3">
  <label for="textareaDisabled" class="form-label">Disabled textarea</label>
  <textarea class="form-control" id="textareaDisabled" rows="3" disabled>This textarea is disabled</textarea>
</div>
Select Menus
<!-- Basic select -->
<div class="mb-3">
  <label for="selectBasic" class="form-label">Basic select</label>
  <select class="form-select" id="selectBasic">
    <option selected>Open this select menu</option>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
  </select>
</div>

<!-- Select with default size -->
<div class="mb-3">
  <label for="selectSize" class="form-label">Select with size</label>
  <select class="form-select" id="selectSize" size="3">
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
    <option value="4">Option 4</option>
    <option value="5">Option 5</option>
  </select>
</div>

<!-- Multiple select -->
<div class="mb-3">
  <label for="selectMultiple" class="form-label">Multiple select</label>
  <select class="form-select" id="selectMultiple" multiple size="4">
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
    <option value="4">Option 4</option>
  </select>
  <div class="form-text">Hold Ctrl (Windows) or Cmd (Mac) to select multiple options</div>
</div>

<!-- Disabled select -->
<div class="mb-3">
  <label for="selectDisabled" class="form-label">Disabled select</label>
  <select class="form-select" id="selectDisabled" disabled>
    <option>Disabled select</option>
  </select>
</div>

<!-- Large select -->
<div class="mb-3">
  <label for="selectLg" class="form-label">Large select</label>
  <select class="form-select form-select-lg" id="selectLg">
    <option>Large select option</option>
  </select>
</div>

<!-- Small select -->
<div class="mb-3">
  <label for="selectSm" class="form-label">Small select</label>
  <select class="form-select form-select-sm" id="selectSm">
    <option>Small select option</option>
  </select>
</div>

2. Form Input Sizing

Control the size of form controls using sizing classes.
<!-- Large inputs -->
<div class="mb-3">
  <label for="largeInput" class="form-label">Large input</label>
  <input type="text" class="form-control form-control-lg" id="largeInput" placeholder="Large input">
</div>

<!-- Default input -->
<div class="mb-3">
  <label for="defaultInput" class="form-label">Default input</label>
  <input type="text" class="form-control" id="defaultInput" placeholder="Default input">
</div>

<!-- Small input -->
<div class="mb-3">
  <label for="smallInput" class="form-label">Small input</label>
  <input type="text" class="form-control form-control-sm" id="smallInput" placeholder="Small input">
</div>

<!-- Large textarea -->
<div class="mb-3">
  <label for="largeTextarea" class="form-label">Large textarea</label>
  <textarea class="form-control form-control-lg" id="largeTextarea" rows="3" placeholder="Large textarea"></textarea>
</div>

<!-- Small textarea -->
<div class="mb-3">
  <label for="smallTextarea" class="form-label">Small textarea</label>
  <textarea class="form-control form-control-sm" id="smallTextarea" rows="2" placeholder="Small textarea"></textarea>
</div>

3. Checkboxes and Radios

Basic Checkboxes
<!-- Basic checkbox -->
<div class="mb-3">
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="checkbox1">
    <label class="form-check-label" for="checkbox1">
      Default checkbox
    </label>
  </div>
</div>

<!-- Checked checkbox -->
<div class="mb-3">
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="checkboxChecked" checked>
    <label class="form-check-label" for="checkboxChecked">
      Checked checkbox
    </label>
  </div>
</div>

<!-- Disabled checkbox -->
<div class="mb-3">
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="checkboxDisabled" disabled>
    <label class="form-check-label" for="checkboxDisabled">
      Disabled checkbox
    </label>
  </div>
</div>

<!-- Multiple checkboxes -->
<div class="mb-3">
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="check1">
    <label class="form-check-label" for="check1">Option 1</label>
  </div>
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="check2">
    <label class="form-check-label" for="check2">Option 2</label>
  </div>
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="check3">
    <label class="form-check-label" for="check3">Option 3</label>
  </div>
</div>

<!-- Inline checkboxes -->
<div class="mb-3">
  <div class="form-check form-check-inline">
    <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1">
    <label class="form-check-label" for="inlineCheckbox1">1</label>
  </div>
  <div class="form-check form-check-inline">
    <input class="form-check-input" type="checkbox" id="inlineCheckbox2" value="option2">
    <label class="form-check-label" for="inlineCheckbox2">2</label>
  </div>
  <div class="form-check form-check-inline">
    <input class="form-check-input" type="checkbox" id="inlineCheckbox3" value="option3" disabled>
    <label class="form-check-label" for="inlineCheckbox3">3 (disabled)</label>
  </div>
</div>

<!-- Indeterminate checkbox (via JavaScript) -->
<div class="mb-3">
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="indeterminateCheckbox">
    <label class="form-check-label" for="indeterminateCheckbox">
      Indeterminate checkbox
    </label>
  </div>
</div>

<script>
  const indeterminateCheckbox = document.getElementById('indeterminateCheckbox');
  if (indeterminateCheckbox) {
    indeterminateCheckbox.indeterminate = true;
  }
</script>
Basic Radio Buttons
<!-- Basic radio buttons -->
<div class="mb-3">
  <div class="form-check">
    <input class="form-check-input" type="radio" name="radioGroup" id="radio1" checked>
    <label class="form-check-label" for="radio1">
      Option 1
    </label>
  </div>
  <div class="form-check">
    <input class="form-check-input" type="radio" name="radioGroup" id="radio2">
    <label class="form-check-label" for="radio2">
      Option 2
    </label>
  </div>
  <div class="form-check">
    <input class="form-check-input" type="radio" name="radioGroup" id="radio3" disabled>
    <label class="form-check-label" for="radio3">
      Option 3 (disabled)
    </label>
  </div>
</div>

<!-- Inline radio buttons -->
<div class="mb-3">
  <div class="form-check form-check-inline">
    <input class="form-check-input" type="radio" name="inlineRadioGroup" id="inlineRadio1" value="option1">
    <label class="form-check-label" for="inlineRadio1">Option 1</label>
  </div>
  <div class="form-check form-check-inline">
    <input class="form-check-input" type="radio" name="inlineRadioGroup" id="inlineRadio2" value="option2">
    <label class="form-check-label" for="inlineRadio2">Option 2</label>
  </div>
  <div class="form-check form-check-inline">
    <input class="form-check-input" type="radio" name="inlineRadioGroup" id="inlineRadio3" value="option3" disabled>
    <label class="form-check-label" for="inlineRadio3">Option 3 (disabled)</label>
  </div>
</div>
Switch Checkboxes (Toggle Switches)
<!-- Basic switch -->
<div class="mb-3">
  <div class="form-check form-switch">
    <input class="form-check-input" type="checkbox" role="switch" id="switch1">
    <label class="form-check-label" for="switch1">Default switch</label>
  </div>
</div>

<!-- Checked switch -->
<div class="mb-3">
  <div class="form-check form-switch">
    <input class="form-check-input" type="checkbox" role="switch" id="switchChecked" checked>
    <label class="form-check-label" for="switchChecked">Checked switch</label>
  </div>
</div>

<!-- Disabled switch -->
<div class="mb-3">
  <div class="form-check form-switch">
    <input class="form-check-input" type="checkbox" role="switch" id="switchDisabled" disabled>
    <label class="form-check-label" for="switchDisabled">Disabled switch</label>
  </div>
</div>

<!-- Large text with switch -->
<div class="mb-3">
  <div class="form-check form-switch">
    <input class="form-check-input" type="checkbox" role="switch" id="switchLarge">
    <label class="form-check-label" for="switchLarge">
      <strong>Enable notifications</strong>
      <div class="text-muted small">Receive email notifications about your account activity</div>
    </label>
  </div>
</div>

4. Form Layouts

Vertical Form (Default)
<form>
  <div class="mb-3">
    <label for="name" class="form-label">Name</label>
    <input type="text" class="form-control" id="name" placeholder="Enter your name">
  </div>
  <div class="mb-3">
    <label for="email" class="form-label">Email address</label>
    <input type="email" class="form-control" id="email" placeholder="name@example.com">
  </div>
  <div class="mb-3">
    <label for="message" class="form-label">Message</label>
    <textarea class="form-control" id="message" rows="3"></textarea>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>
Horizontal Form (Using Grid)
<form>
  <div class="row mb-3">
    <label for="horizontalEmail" class="col-sm-2 col-form-label">Email</label>
    <div class="col-sm-10">
      <input type="email" class="form-control" id="horizontalEmail" placeholder="email@example.com">
    </div>
  </div>
  <div class="row mb-3">
    <label for="horizontalPassword" class="col-sm-2 col-form-label">Password</label>
    <div class="col-sm-10">
      <input type="password" class="form-control" id="horizontalPassword" placeholder="Password">
    </div>
  </div>
  <fieldset class="row mb-3">
    <legend class="col-form-label col-sm-2 pt-0">Radios</legend>
    <div class="col-sm-10">
      <div class="form-check">
        <input class="form-check-input" type="radio" name="gridRadios" id="gridRadios1" value="option1" checked>
        <label class="form-check-label" for="gridRadios1">First radio</label>
      </div>
      <div class="form-check">
        <input class="form-check-input" type="radio" name="gridRadios" id="gridRadios2" value="option2">
        <label class="form-check-label" for="gridRadios2">Second radio</label>
      </div>
    </div>
  </fieldset>
  <div class="row mb-3">
    <div class="col-sm-10 offset-sm-2">
      <div class="form-check">
        <input class="form-check-input" type="checkbox" id="gridCheck">
        <label class="form-check-label" for="gridCheck">Remember me</label>
      </div>
    </div>
  </div>
  <button type="submit" class="btn btn-primary">Sign in</button>
</form>
Inline Form
<form class="row g-3 align-items-center">
  <div class="col-auto">
    <label for="inlineName" class="visually-hidden">Name</label>
    <input type="text" class="form-control" id="inlineName" placeholder="Jane Doe">
  </div>
  <div class="col-auto">
    <label for="inlineEmail" class="visually-hidden">Email</label>
    <input type="email" class="form-control" id="inlineEmail" placeholder="name@example.com">
  </div>
  <div class="col-auto">
    <div class="form-check">
      <input class="form-check-input" type="checkbox" id="inlineCheck">
      <label class="form-check-label" for="inlineCheck">Remember me</label>
    </div>
  </div>
  <div class="col-auto">
    <button type="submit" class="btn btn-primary">Submit</button>
  </div>
</form>
Form Grid with Multiple Columns
<div class="row g-3">
  <div class="col-md-6">
    <label for="firstName" class="form-label">First name</label>
    <input type="text" class="form-control" id="firstName" required>
  </div>
  <div class="col-md-6">
    <label for="lastName" class="form-label">Last name</label>
    <input type="text" class="form-control" id="lastName" required>
  </div>
  <div class="col-md-6">
    <label for="city" class="form-label">City</label>
    <input type="text" class="form-control" id="city">
  </div>
  <div class="col-md-4">
    <label for="state" class="form-label">State</label>
    <select class="form-select" id="state">
      <option selected>Choose...</option>
      <option>California</option>
      <option>New York</option>
      <option>Texas</option>
    </select>
  </div>
  <div class="col-md-2">
    <label for="zip" class="form-label">Zip</label>
    <input type="text" class="form-control" id="zip">
  </div>
</div>
Auto-sizing with Column Classes
<div class="row g-3 align-items-center">
  <div class="col-auto">
    <label for="autoName" class="visually-hidden">Name</label>
    <input type="text" class="form-control" id="autoName" placeholder="Name">
  </div>
  <div class="col-auto">
    <label for="autoEmail" class="visually-hidden">Email</label>
    <input type="email" class="form-control" id="autoEmail" placeholder="Email">
  </div>
  <div class="col-auto">
    <button type="submit" class="btn btn-primary">Submit</button>
  </div>
</div>

5. Floating Labels

Floating labels are form labels that float above the input field when it's filled or focused.
<!-- Basic floating label -->
<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>

<!-- Floating label with value pre-filled -->
<div class="form-floating mb-3">
  <input type="text" class="form-control" id="floatingName" placeholder="Name" value="John Doe">
  <label for="floatingName">Full name</label>
</div>

<!-- Floating label with textarea -->
<div class="form-floating mb-3">
  <textarea class="form-control" placeholder="Leave a comment here" id="floatingTextarea" style="height: 100px"></textarea>
  <label for="floatingTextarea">Comments</label>
</div>

<!-- Floating select -->
<div class="form-floating mb-3">
  <select class="form-select" id="floatingSelect" aria-label="Floating label select">
    <option selected>Open this select menu</option>
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
    <option value="3">Option 3</option>
  </select>
  <label for="floatingSelect">Select an option</label>
</div>

<!-- Floating disabled -->
<div class="form-floating mb-3">
  <input type="text" class="form-control" id="floatingDisabled" placeholder="Disabled" disabled value="Disabled input">
  <label for="floatingDisabled">Disabled input</label>
</div>

<!-- Floating readonly -->
<div class="form-floating mb-3">
  <input type="text" class="form-control" id="floatingReadonly" placeholder="Readonly" readonly value="Readonly input">
  <label for="floatingReadonly">Readonly input</label>
</div>

<!-- Floating labels grid layout -->
<div class="row g-2">
  <div class="col-md">
    <div class="form-floating">
      <input type="email" class="form-control" id="floatingGridEmail" placeholder="name@example.com">
      <label for="floatingGridEmail">Email address</label>
    </div>
  </div>
  <div class="col-md">
    <div class="form-floating">
      <select class="form-select" id="floatingGridSelect" aria-label="Floating label select">
        <option selected>Open this select menu</option>
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
      </select>
      <label for="floatingGridSelect">Works with selects</label>
    </div>
  </div>
</div>

6. Input Groups

Input groups allow you to add text, buttons, or other elements before or after input fields.
<!-- Basic input group with text -->
<div class="input-group mb-3">
  <span class="input-group-text" id="basic-addon1">@</span>
  <input type="text" class="form-control" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1">
</div>

<!-- Input group with text on both sides -->
<div class="input-group mb-3">
  <span class="input-group-text">$</span>
  <input type="text" class="form-control" aria-label="Amount (to the nearest dollar)">
  <span class="input-group-text">.00</span>
</div>

<!-- Input group with button -->
<div class="input-group mb-3">
  <input type="text" class="form-control" placeholder="Recipient's username" aria-label="Recipient's username">
  <button class="btn btn-outline-secondary" type="button">Button</button>
</div>

<!-- Input group with dropdown button -->
<div class="input-group mb-3">
  <button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
    Dropdown
  </button>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#">Action</a></li>
    <li><a class="dropdown-item" href="#">Another action</a></li>
  </ul>
  <input type="text" class="form-control" aria-label="Text input with dropdown button">
</div>

<!-- Input group with checkbox and radio -->
<div class="input-group mb-3">
  <div class="input-group-text">
    <input class="form-check-input mt-0" type="checkbox" value="" aria-label="Checkbox for following text input">
  </div>
  <input type="text" class="form-control" aria-label="Text input with checkbox">
</div>

<div class="input-group mb-3">
  <div class="input-group-text">
    <input class="form-check-input mt-0" type="radio" value="" aria-label="Radio button for following text input">
  </div>
  <input type="text" class="form-control" aria-label="Text input with radio button">
</div>

<!-- Input group with multiple addons -->
<div class="input-group mb-3">
  <span class="input-group-text">https://</span>
  <span class="input-group-text">www.</span>
  <input type="text" class="form-control" placeholder="example.com">
  <span class="input-group-text">.com</span>
</div>

<!-- Input group sizing -->
<div class="input-group input-group-lg mb-3">
  <span class="input-group-text">Large</span>
  <input type="text" class="form-control" placeholder="Large input">
</div>

<div class="input-group input-group-sm mb-3">
  <span class="input-group-text">Small</span>
  <input type="text" class="form-control" placeholder="Small input">
</div>

7. Form Validation

Bootstrap provides validation styles for forms using either browser default validation or custom validation with JavaScript.
Custom Validation (with JavaScript)
<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 first name.</div>
  </div>
  <div class="col-md-4">
    <label for="validationLast" class="form-label">Last name</label>
    <input type="text" class="form-control" id="validationLast" required>
    <div class="valid-feedback">Looks good!</div>
    <div class="invalid-feedback">Please enter your last name.</div>
  </div>
  <div class="col-md-4">
    <label for="validationEmail" class="form-label">Email</label>
    <div class="input-group has-validation">
      <span class="input-group-text" id="inputGroupPrepend">@</span>
      <input type="email" class="form-control" id="validationEmail" aria-describedby="inputGroupPrepend" required>
      <div class="invalid-feedback">Please choose a valid email.</div>
    </div>
  </div>
  <div class="col-md-6">
    <label for="validationCity" class="form-label">City</label>
    <input type="text" class="form-control" id="validationCity" required>
    <div class="invalid-feedback">Please provide a valid city.</div>
  </div>
  <div class="col-md-3">
    <label for="validationState" class="form-label">State</label>
    <select class="form-select" id="validationState" required>
      <option selected disabled value="">Choose...</option>
      <option>California</option>
      <option>New York</option>
      <option>Texas</option>
    </select>
    <div class="invalid-feedback">Please select a valid state.</div>
  </div>
  <div class="col-md-3">
    <label for="validationZip" class="form-label">Zip</label>
    <input type="text" class="form-control" id="validationZip" required>
    <div class="invalid-feedback">Please provide a valid zip code.</div>
  </div>
  <div class="col-12">
    <div class="form-check">
      <input class="form-check-input" type="checkbox" value="" id="invalidCheck" required>
      <label class="form-check-label" for="invalidCheck">
        Agree to terms and conditions
      </label>
      <div class="invalid-feedback">You must agree before submitting.</div>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Submit form</button>
  </div>
</form>

<script>
  (function() {
    '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>
Browser Default Validation
<form>
  <div class="mb-3">
    <label for="defaultName" class="form-label">Name</label>
    <input type="text" class="form-control" id="defaultName" required>
  </div>
  <div class="mb-3">
    <label for="defaultEmail" class="form-label">Email</label>
    <input type="email" class="form-control" id="defaultEmail" required>
  </div>
  <div class="mb-3">
    <label for="defaultSelect" class="form-label">Select</label>
    <select class="form-select" id="defaultSelect" required>
      <option value="">Choose...</option>
      <option>Option 1</option>
      <option>Option 2</option>
    </select>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>
Validation with Icons
<form class="row g-3">
  <div class="col-md-4">
    <label for="iconName" class="form-label">First name</label>
    <input type="text" class="form-control is-valid" id="iconName" value="John">
    <div class="valid-feedback">Looks good!</div>
  </div>
  <div class="col-md-4">
    <label for="iconLast" class="form-label">Last name</label>
    <input type="text" class="form-control is-invalid" id="iconLast" value="Doe">
    <div class="invalid-feedback">Please enter a valid last name.</div>
  </div>
  <div class="col-md-4">
    <label for="iconEmail" class="form-label">Email</label>
    <div class="input-group has-validation">
      <span class="input-group-text">@</span>
      <input type="email" class="form-control is-invalid" id="iconEmail" value="invalidemail">
      <div class="invalid-feedback">Please enter a valid email.</div>
    </div>
  </div>
</form>
Server-side Validation
<!-- Form with server-side validation classes -->
<form>
  <div class="mb-3">
    <label for="serverName" class="form-label">Name</label>
    <input type="text" class="form-control is-invalid" id="serverName">
    <div class="invalid-feedback">
      This name is already taken.
    </div>
  </div>
  <div class="mb-3">
    <label for="serverEmail" class="form-label">Email</label>
    <input type="email" class="form-control is-valid" id="serverEmail">
    <div class="valid-feedback">
      Email address is available.
    </div>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>

8. Custom Form Controls

Range Slider with Values
<label for="customRange" class="form-label">Example range</label>
<input type="range" class="form-range" id="customRange">

<label for="customRange2" class="form-label">Range with steps</label>
<input type="range" class="form-range" min="0" max="100" step="10" id="customRange2">

<label for="customRange3" class="form-label">Range with values display</label>
<div class="d-flex justify-content-between">
  <span>0</span>
  <span>25</span>
  <span>50</span>
  <span>75</span>
  <span>100</span>
</div>
<input type="range" class="form-range" min="0" max="100" id="customRange3">
File Upload
<!-- Basic file input -->
<div class="mb-3">
  <label for="fileInput" class="form-label">File upload</label>
  <input class="form-control" type="file" id="fileInput">
</div>

<!-- Multiple files -->
<div class="mb-3">
  <label for="multipleFiles" class="form-label">Multiple files</label>
  <input class="form-control" type="file" id="multipleFiles" multiple>
</div>

<!-- Disabled file input -->
<div class="mb-3">
  <label for="disabledFile" class="form-label">Disabled file input</label>
  <input class="form-control" type="file" id="disabledFile" disabled>
</div>

<!-- File input with custom button styling -->
<div class="mb-3">
  <label for="customFile" class="form-label">Custom file input</label>
  <input class="form-control" type="file" id="customFile" accept="image/*">
</div>

<!-- File input with preview (JavaScript) -->
<div class="mb-3">
  <label for="fileWithPreview" class="form-label">File upload with preview</label>
  <input class="form-control" type="file" id="fileWithPreview" accept="image/*">
  <img id="imagePreview" src="#" alt="Preview" style="max-width: 200px; margin-top: 10px; display: none;">
</div>

<script>
  document.getElementById('fileWithPreview')?.addEventListener('change', function(event) {
    const preview = document.getElementById('imagePreview');
    if (event.target.files && event.target.files[0]) {
      const reader = new FileReader();
      reader.onload = function(e) {
        preview.src = e.target.result;
        preview.style.display = 'block';
      };
      reader.readAsDataURL(event.target.files[0]);
    }
  });
</script>
Datalist (Autocomplete)
<div class="mb-3">
  <label for="browser" class="form-label">Choose your favorite browser</label>
  <input class="form-control" list="browserOptions" id="browser" placeholder="Type to search...">
  <datalist id="browserOptions">
    <option value="Chrome">
    <option value="Firefox">
    <option value="Safari">
    <option value="Edge">
    <option value="Opera">
    <option value="Brave">
  </datalist>
</div>

9. Form Help Text

<!-- Basic help text -->
<div class="mb-3">
  <label for="passwordHelp" class="form-label">Password</label>
  <input type="password" class="form-control" id="passwordHelp">
  <div class="form-text">Your password must be 8-20 characters long.</div>
</div>

<!-- Help text with list -->
<div class="mb-3">
  <label for="passwordRequirements" class="form-label">Password</label>
  <input type="password" class="form-control" id="passwordRequirements">
  <div class="form-text">
    Password requirements:
    <ul class="mb-0 mt-1">
      <li>At least 8 characters</li>
      <li>One uppercase letter</li>
      <li>One number</li>
      <li>One special character</li>
    </ul>
  </div>
</div>

10. Complete Form Examples

Registration Form Example
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Registration Form - Bootstrap 5</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
</head>
<body class="bg-light">
  <div class="container py-5">
    <div class="row justify-content-center">
      <div class="col-md-8 col-lg-6">
        <div class="card shadow">
          <div class="card-header bg-primary text-white text-center py-3">
            <h4 class="mb-0"><i class="bi bi-person-plus-fill"></i> Create an Account</h4>
          </div>
          <div class="card-body p-4">
            <form class="needs-validation" novalidate>
              <div class="row mb-3">
                <div class="col-md-6">
                  <label for="firstName" class="form-label">First name</label>
                  <input type="text" class="form-control" id="firstName" required>
                  <div class="invalid-feedback">First name is required.</div>
                </div>
                <div class="col-md-6">
                  <label for="lastName" class="form-label">Last name</label>
                  <input type="text" class="form-control" id="lastName" required>
                  <div class="invalid-feedback">Last name is required.</div>
                </div>
              </div>
              
              <div class="mb-3">
                <label for="email" class="form-label">Email address</label>
                <div class="input-group">
                  <span class="input-group-text"><i class="bi bi-envelope"></i></span>
                  <input type="email" class="form-control" id="email" placeholder="name@example.com" required>
                  <div class="invalid-feedback">Please enter a valid email address.</div>
                </div>
              </div>
              
              <div class="mb-3">
                <label for="password" class="form-label">Password</label>
                <div class="input-group">
                  <span class="input-group-text"><i class="bi bi-lock"></i></span>
                  <input type="password" class="form-control" id="password" required>
                  <div class="invalid-feedback">Password is required.</div>
                </div>
                <div class="form-text">Password must be at least 8 characters.</div>
              </div>
              
              <div class="mb-3">
                <label for="confirmPassword" class="form-label">Confirm Password</label>
                <div class="input-group">
                  <span class="input-group-text"><i class="bi bi-lock-fill"></i></span>
                  <input type="password" class="form-control" id="confirmPassword" required>
                  <div class="invalid-feedback">Please confirm your password.</div>
                </div>
              </div>
              
              <div class="mb-3">
                <label for="country" class="form-label">Country</label>
                <select class="form-select" id="country" required>
                  <option selected disabled value="">Choose...</option>
                  <option>United States</option>
                  <option>Canada</option>
                  <option>United Kingdom</option>
                  <option>Australia</option>
                  <option>Other</option>
                </select>
                <div class="invalid-feedback">Please select your country.</div>
              </div>
              
              <div class="mb-3">
                <label class="form-label d-block">How did you hear about us?</label>
                <div class="form-check form-check-inline">
                  <input class="form-check-input" type="checkbox" id="socialMedia" value="social">
                  <label class="form-check-label" for="socialMedia">Social Media</label>
                </div>
                <div class="form-check form-check-inline">
                  <input class="form-check-input" type="checkbox" id="friend" value="friend">
                  <label class="form-check-label" for="friend">Friend</label>
                </div>
                <div class="form-check form-check-inline">
                  <input class="form-check-input" type="checkbox" id="advertisement" value="ad">
                  <label class="form-check-label" for="advertisement">Advertisement</label>
                </div>
                <div class="form-check form-check-inline">
                  <input class="form-check-input" type="checkbox" id="other" value="other">
                  <label class="form-check-label" for="other">Other</label>
                </div>
              </div>
              
              <div class="mb-3">
                <div class="form-check">
                  <input class="form-check-input" type="checkbox" id="terms" required>
                  <label class="form-check-label" for="terms">
                    I agree to the <a href="#">Terms and Conditions</a>
                  </label>
                  <div class="invalid-feedback">You must agree to the terms.</div>
                </div>
              </div>
              
              <div class="mb-3">
                <div class="form-check form-switch">
                  <input class="form-check-input" type="checkbox" role="switch" id="newsletter">
                  <label class="form-check-label" for="newsletter">
                    Subscribe to newsletter
                  </label>
                </div>
              </div>
              
              <div class="d-grid gap-2">
                <button class="btn btn-primary btn-lg" type="submit">
                  <i class="bi bi-check-circle"></i> Register
                </button>
                <p class="text-center text-muted mt-3 mb-0">
                  Already have an account? <a href="#">Sign in</a>
                </p>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
  <script>
    (function() {
      'use strict';
      const forms = document.querySelectorAll('.needs-validation');
      Array.from(forms).forEach(form => {
        form.addEventListener('submit', event => {
          const password = document.getElementById('password').value;
          const confirmPassword = document.getElementById('confirmPassword').value;
          
          if (password !== confirmPassword) {
            event.preventDefault();
            event.stopPropagation();
            document.getElementById('confirmPassword').setCustomValidity('Passwords do not match');
          } else {
            document.getElementById('confirmPassword').setCustomValidity('');
          }
          
          if (!form.checkValidity()) {
            event.preventDefault();
            event.stopPropagation();
          }
          
          form.classList.add('was-validated');
        }, false);
      });
    })();
  </script>
</body>
</html>
Contact Form Example
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Contact Form - Bootstrap 5</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
</head>
<body class="bg-light">
  <div class="container py-5">
    <div class="row">
      <div class="col-lg-8 mx-auto">
        <div class="card border-0 shadow">
          <div class="card-body p-5">
            <div class="text-center mb-4">
              <i class="bi bi-envelope-paper fs-1 text-primary"></i>
              <h2 class="mt-2">Contact Us</h2>
              <p class="text-muted">We'd love to hear from you. Send us a message and we'll respond as soon as possible.</p>
            </div>
            
            <form action="#" method="POST">
              <div class="row mb-3">
                <div class="col-md-6">
                  <label for="contactName" class="form-label">Full name</label>
                  <div class="input-group">
                    <span class="input-group-text"><i class="bi bi-person"></i></span>
                    <input type="text" class="form-control" id="contactName" placeholder="John Doe" required>
                  </div>
                </div>
                <div class="col-md-6">
                  <label for="contactEmail" class="form-label">Email address</label>
                  <div class="input-group">
                    <span class="input-group-text"><i class="bi bi-envelope"></i></span>
                    <input type="email" class="form-control" id="contactEmail" placeholder="john@example.com" required>
                  </div>
                </div>
              </div>
              
              <div class="mb-3">
                <label for="contactSubject" class="form-label">Subject</label>
                <div class="input-group">
                  <span class="input-group-text"><i class="bi bi-chat"></i></span>
                  <input type="text" class="form-control" id="contactSubject" placeholder="What is this regarding?" required>
                </div>
              </div>
              
              <div class="mb-3">
                <label for="contactMessage" class="form-label">Message</label>
                <div class="input-group">
                  <span class="input-group-text"><i class="bi bi-pencil"></i></span>
                  <textarea class="form-control" id="contactMessage" rows="5" placeholder="Please provide details..." required></textarea>
                </div>
              </div>
              
              <div class="mb-4">
                <label class="form-label d-block">Preferred contact method</label>
                <div class="form-check form-check-inline">
                  <input class="form-check-input" type="radio" name="contactMethod" id="methodEmail" checked>
                  <label class="form-check-label" for="methodEmail">Email</label>
                </div>
                <div class="form-check form-check-inline">
                  <input class="form-check-input" type="radio" name="contactMethod" id="methodPhone">
                  <label class="form-check-label" for="methodPhone">Phone</label>
                </div>
              </div>
              
              <div class="mb-4">
                <div class="form-check">
                  <input class="form-check-input" type="checkbox" id="contactCopy" checked>
                  <label class="form-check-label" for="contactCopy">
                    Send me a copy of this message
                  </label>
                </div>
              </div>
              
              <div class="d-grid">
                <button type="submit" class="btn btn-primary btn-lg">
                  <i class="bi bi-send"></i> Send Message
                </button>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Quick Reference Table

ClassPurpose
.form-controlText inputs, textareas, selects
.form-selectSelect dropdowns
.form-checkCheckboxes and radios container
.form-check-inputCheckbox/radio input element
.form-check-labelLabel for checkboxes/radios
.form-switchToggle switch styling
.form-rangeRange slider styling
.form-floatingFloating label container
.input-groupContainer for input groups
.input-group-textText/icon in input group
.form-textHelp text styling
.is-valid / .is-invalidValidation states
.valid-feedback / .invalid-feedbackValidation messages
.was-validatedForm validation class
.form-control-lg / .form-control-smInput sizing
.form-select-lg / .form-select-smSelect sizing
.needs-validationCustom validation form class