Navbar, modal and forms

Assemble a collapsing navbar, drive a modal with data attributes or JavaScript, and use the validation classes for what they are.

<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container-fluid">
    <a class="navbar-brand" href="/">Site</a>
    <button class="navbar-toggler" type="button"
            data-bs-toggle="collapse" data-bs-target="#mainNav"
            aria-controls="mainNav" aria-expanded="false"
            aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="mainNav">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item"><a class="nav-link active" aria-current="page" href="/">Home</a></li>
        <li class="nav-item"><a class="nav-link" href="/docs">Docs</a></li>
      </ul>
    </div>
  </div>
</nav>
  • navbar-expand-lg decides the width at which the menu stops collapsing; without an expand-* class it is always collapsed.
  • The toggler needs data-bs-toggle="collapse" and a data-bs-target that matches the id of the collapsible element.
  • me-auto pushes the later items to the right; mb-2 mb-lg-0 fixes the spacing in collapsed mode only.
  • The aria-* attributes are not decoration: they are how a screen reader learns that the button controls a menu that is currently closed.
<button class="btn btn-primary" data-bs-toggle="modal"
        data-bs-target="#confirmDelete">Delete</button>

<div class="modal fade" id="confirmDelete" tabindex="-1"
     aria-labelledby="confirmDeleteLabel" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h2 class="modal-title fs-5" id="confirmDeleteLabel">Delete this item?</h2>
        <button class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">This action cannot be undone.</div>
      <div class="modal-footer">
        <button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
        <button class="btn btn-danger" id="confirm">Delete</button>
      </div>
    </div>
  </div>
</div>
  • data-bs-toggle="modal" plus data-bs-target opens it with no JavaScript at all.
  • While a modal is open, Bootstrap inserts a backdrop and compensates for the scrollbar gap; the dialog stays where it is in the DOM.
  • modal-dialog-centered centres it vertically and modal-dialog-scrollable keeps the header and footer fixed while the body scrolls.
  • Listen for hidden.bs.modal when you need to clear form state, because that event fires after the transition finishes.

Forms and validation

<form class="row g-3 needs-validation" novalidate>
  <div class="col-md-6">
    <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 address.</div>
  </div>
  <div class="col-md-6">
    <label for="plan" class="form-label">Plan</label>
    <select class="form-select" id="plan" required>
      <option value="">Choose...</option>
      <option>Starter</option>
    </select>
  </div>
  <div class="col-12">
    <div class="form-check">
      <input class="form-check-input" type="checkbox" id="terms" required>
      <label class="form-check-label" for="terms">Accept the terms</label>
      <div class="invalid-feedback">You must accept before continuing.</div>
    </div>
  </div>
  <div class="col-12">
    <button class="btn btn-primary" type="submit">Submit</button>
  </div>
</form>
⚠️
Bootstrap's validation is presentation only: it adds the was-validated class and toggles the feedback elements, and nothing else. Validate again on the server and never treat a green border as evidence that the data is safe.

FAQ

How do I open a modal from JavaScript?
Create the instance with new bootstrap.Modal('#confirmDelete') and call .show() or .hide(). React to the shown.bs.modal and hidden.bs.modal events instead of polling for the class.
Why does my dropdown or tooltip do nothing?
The interactive components need the Bootstrap bundle script, which includes Popper. Without it the CSS and the markup render correctly and the behaviour simply never initialises.

The grid system Forms and inputs

Last refreshed 2026-09-18.