LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1920 min read

Modals

Learn Bootstrap's modal component structure, triggering modals with data-bs-toggle/data-bs-target, sizes, and the JavaScript API.

Introduction

A modal is a dialog box that overlays the current page, forcing the user's attention onto a focused task — confirming a delete, showing a form, or displaying extra details — without navigating away. Bootstrap's modal component handles the overlay, focus trapping, and open/close animation entirely through data attributes, with no custom JavaScript required for the basic case.

What You Will Learn
  • The full modal markup structure.
  • How to trigger a modal with data-bs-toggle and data-bs-target.
  • Modal sizes, scrolling, and centering options.
  • How to open/close modals from your own JavaScript.

A modal is built from a nested set of divs: `.modal` (the outer wrapper, hidden by default), `.modal-dialog` (sizing/positioning), and `.modal-content` (the visible bordered box holding the actual content).

<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<!-- header, body, footer go here -->
</div>
</div>
</div>
What Renders

Click Run to see what this code prints.

A button opens the modal declaratively using `data-bs-toggle="modal"` and `data-bs-target="#modalId"`, matching the modal's `id`. No JavaScript is needed for this basic trigger — Bootstrap's bundled JS listens for the click automatically.

<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
Open Modal
</button>
What Renders

Click Run to see what this code prints.

Inside `.modal-content`, use `.modal-header` for the title and close button, `.modal-body` for the main content, and `.modal-footer` for action buttons like Save/Cancel.

<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Confirm Action</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete this course?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger">Delete</button>
</div>
</div>
What Renders

Click Run to see what this code prints.

Add `.modal-sm`, `.modal-lg`, or `.modal-xl` to `.modal-dialog` to control its width. Leaving the size class off gives you Bootstrap's default medium width.

<div class="modal-dialog modal-lg">
<div class="modal-content"><!-- ... --></div>
</div>
What Renders

Click Run to see what this code prints.

`.modal-dialog-scrollable` keeps the header and footer fixed while only `.modal-body` scrolls internally when content is too tall for the viewport. `.modal-dialog-centered` vertically centers the whole dialog in the viewport instead of pinning it near the top.

<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content"><!-- long content --></div>
</div>
What Renders

Click Run to see what this code prints.

By default, clicking outside a modal or pressing Escape closes it. Set `data-bs-backdrop="static"` to prevent closing on an outside click (the modal will "shake" instead), and `data-bs-keyboard="false"` to disable the Escape key too — useful for forms that shouldn't be dismissed accidentally.

<div class="modal" id="forceModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
<!-- ... -->
</div>
What Renders

Click Run to see what this code prints.

When you need to open or close a modal programmatically (for example, after an async action succeeds), use Bootstrap's JavaScript Modal API instead of the data attributes.

const modalEl = document.getElementById('exampleModal');
const modal = new bootstrap.Modal(modalEl);
modal.show();
// later...
modal.hide();
What Renders

Click Run to see what this code prints.

Common Mistakes

Avoid These Mistakes
  • Mismatched id and data-bs-target values, so the button click does nothing.
  • Nesting one modal directly inside another, which Bootstrap explicitly does not support.
  • Forgetting tabindex="-1" on the outer .modal element, hurting keyboard focus behavior.
  • Putting position: fixed elements inside a modal body, which can behave unpredictably with the modal's own positioning.

Best Practices

  • Use data-bs-backdrop="static" for forms or destructive confirmations that shouldn't close accidentally.
  • Keep modal content focused on a single task — avoid stuffing entire pages into a modal.
  • Always include a visible close button in addition to backdrop/Escape dismissal.
  • Use modal-dialog-centered for short confirmation dialogs to keep them visually balanced.
  • Reset form fields inside a modal when it closes, using the hidden.bs.modal event.

Frequently Asked Questions

Yes, as long as each modal has a unique id and its trigger uses the matching data-bs-target, but avoid opening one modal from within another.

Listen for the shown.bs.modal event on the modal element, which fires once the open animation completes.

No, Bootstrap locks body scrolling while a modal is open and restores it automatically when the modal closes.

Yes, use the JavaScript API (new bootstrap.Modal(el).show()) to open a modal from any event, such as a page load or a fetch callback.

Key Takeaways

  • Modals nest .modal > .modal-dialog > .modal-content.
  • Trigger buttons use data-bs-toggle="modal" and data-bs-target="#id" matching the modal.
  • .modal-header, .modal-body, and .modal-footer structure the visible content.
  • .modal-sm/.modal-lg/.modal-xl control width; modal-dialog-centered controls vertical position.
  • data-bs-backdrop="static" and data-bs-keyboard="false" prevent accidental dismissal.
  • The JavaScript Modal API (show()/hide()) lets you control modals outside of a click trigger.

Summary

Modals give you a clean way to interrupt the user's flow for a focused task, without the complexity of managing a separate page. With the header/body/footer structure and the data-bs-* trigger pattern, you can build confirmation dialogs, forms, and detail views entirely declaratively. Next, you'll learn dropdowns, another component built on the same data-bs-toggle pattern.

Next Lesson →

Dropdowns