Modal

A Modal is a dialog box that pops up on top of the page — used for confirmations, forms, or anything that needs the user's focus before they can continue. Bootstrap 4's Modal, like every other interactive component in this section, is a jQuery plugin under the hood, but you rarely need to write any JS yourself: the data-toggle/data-target attribute API opens and closes it declaratively. We'll build a "Confirm trail submission" modal for TrailMap, our hiking trail directory app.

Modal Structure

Every modal is built from the same nested structure: an outer .modal wrapper (hidden by default), a .modal-dialog that sizes and centers the box, and a .modal-content box split into .modal-header, .modal-body, and .modal-footer.

<div class="modal fade" id="confirmTrailModal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Title</h5>
        <button type="button" class="close" data-dismiss="modal">
          <span>&times;</span>
        </button>
      </div>
      <div class="modal-body">Body content</div>
      <div class="modal-footer">Footer buttons</div>
    </div>
  </div>
</div>

Triggering a Modal Declaratively

The button or link that opens the modal needs two attributes: data-toggle="modal" tells Bootstrap this element opens a modal, and data-target points at the modal's id (prefixed with #). No JavaScript required.

<button type="button" class="btn btn-primary"
  data-toggle="modal" data-target="#confirmTrailModal">
  Submit Trail
</button>
Note: This is data-toggle/data-target, not Bootstrap 5's data-bs-toggle/data-bs-target. Bootstrap 4's attribute API has no bs- prefix.

Sizing Modals

Add a size class alongside .modal-dialog to change the width: .modal-sm for a small modal, .modal-lg for a large one, or leave it off for the default medium size.

<div class="modal-dialog modal-lg" role="document"> ... </div>

Worked Example: TrailMap "Confirm Trail Submission" Modal

When a hiker submits a new trail to TrailMap, we confirm the details in a modal before it goes off for review.

<button type="button" class="btn btn-primary"
  data-toggle="modal" data-target="#confirmTrailModal">
  Submit Trail
</button>

<div class="modal fade" id="confirmTrailModal" tabindex="-1" role="dialog" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Confirm Trail Submission</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <p>You're about to submit <strong>Ridgeline Loop</strong> (4.2 mi, Moderate) for review. A moderator will approve it within 48 hours.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
        <button type="button" class="btn btn-primary">Confirm Submission</button>
      </div>
    </div>
  </div>
</div>

Triggering a Modal From jQuery

Sometimes you need to open or close a modal from custom JS — after an AJAX call succeeds, for example — instead of a user click. The Modal plugin exposes a jQuery method, .modal(), that takes 'show', 'hide', or 'toggle'.

// Open the modal from custom JS, e.g. after validating a form
$('#confirmTrailModal').modal('show');

// Close it programmatically
$('#confirmTrailModal').modal('hide');
Up next: Modal's show/hide animation is a special case of a more general pattern — sliding content open and closed — which is exactly what the Collapse component does.