Modal

Compose dialogs with captured header, body, footer, close button, sizing, scroll behavior, and Bootstrap modal data APIs.

How it works

Modals are positioned over the document and use Bootstrap's JavaScript plugin for focus management, backdrop behavior, keyboard dismissal, and transitions. Only one modal should be open at a time unless you explicitly toggle from one modal to another.

Bootstrap modals use position: fixed, remove body scrolling while open, and respect reduced-motion settings for transitions. Avoid nesting modals; use the documented toggle pattern when a workflow must move from one dialog to another.

The BCL modal helper renders the modal shell and captures bs-modal-header, bs-modal-body, and bs-modal-footer. Use bs-button for launch and dismiss controls, with Bootstrap data-bs-* attributes where the behavior belongs to the JavaScript plugin.

Modal components

Use a header for the title and close button, a required body for padded content, and an optional footer for actions. Keep the visible title level coherent with the surrounding page.

aspnet

<bs-button btn-style="Primary" data-bs-toggle="modal" data-bs-target="#docsModal">Launch modal</bs-button>
<bs-modal id="docsModal" dialog-id="docsModalDialog" fade="true">
    <bs-modal-header modal-title="Modal title">
        <bs-close-button data-bs-dismiss="modal" aria-label="Close" />
    </bs-modal-header>
    <bs-modal-body>
        <bs-p>Modal body text goes here.</bs-p>
    </bs-modal-body>
    <bs-modal-footer>
        <bs-button btn-style="Secondary" data-bs-dismiss="modal">Close</bs-button>
        <bs-button btn-style="Primary">Save changes</bs-button>
    </bs-modal-footer>
</bs-modal>
            

Live demo

Use a trigger with data-bs-toggle="modal" and data-bs-target to open the modal. Footer buttons should dismiss with data-bs-dismiss="modal" when they close the dialog.

aspnet

<bs-button btn-style="Secondary" data-bs-toggle="modal" data-bs-target="#componentsDocsModal">Open component modal</bs-button>
<bs-modal id="componentsDocsModal" dialog-id="componentsDocsModalDialog" fade="true">
    <bs-modal-header modal-title="Confirm request">
        <bs-close-button data-bs-dismiss="modal" aria-label="Close" />
    </bs-modal-header>
    <bs-modal-body>
        <bs-p>This body can contain form controls, alerts, grids, or any other content that belongs in a focused dialog.</bs-p>
    </bs-modal-body>
    <bs-modal-footer>
        <bs-button btn-style="Secondary" data-bs-dismiss="modal">Cancel</bs-button>
        <bs-button btn-style="Primary">Confirm</bs-button>
    </bs-modal-footer>
</bs-modal>
            

Static backdrop

Use backdrop="Static" and keyboard="false" when a modal should not close from backdrop clicks or the Escape key.

aspnet

<bs-button btn-style="Secondary" data-bs-toggle="modal" data-bs-target="#staticDocsModal">Launch static modal</bs-button>
<bs-modal id="staticDocsModal" dialog-id="staticDocsModalDialog" fade="true" backdrop="Static" keyboard="false">
    <bs-modal-header modal-title="Static backdrop">
        <bs-close-button data-bs-dismiss="modal" aria-label="Close" />
    </bs-modal-header>
    <bs-modal-body>Click the close button or footer action to dismiss this modal.</bs-modal-body>
    <bs-modal-footer>
        <bs-button btn-style="Secondary" data-bs-dismiss="modal">Close</bs-button>
    </bs-modal-footer>
</bs-modal>
            

Scrolling long content

Set scrollable="true" when the modal body should scroll independently. If content height changes while the modal is open, call Bootstrap's handleUpdate() method after the change.

aspnet

<bs-button btn-style="Primary" outline="true" data-bs-toggle="modal" data-bs-target="#scrollingDocsModal">Scrollable modal</bs-button>
<bs-modal id="scrollingDocsModal" dialog-id="scrollingDocsModalDialog" fade="true" scrollable="true">
    <bs-modal-header modal-title="Scrollable content">
        <bs-close-button data-bs-dismiss="modal" aria-label="Close" />
    </bs-modal-header>
    <bs-modal-body style="height: 16rem; max-height: 16rem; overflow-y: auto;">
        <bs-div style="min-height: 44rem;">
            <bs-p>Long modal content can scroll independently from the page.</bs-p>
            <bs-p>This final block intentionally adds enough height for the modal body to overflow.</bs-p>
        </bs-div>
    </bs-modal-body>
    <bs-modal-footer>
        <bs-button btn-style="Secondary" data-bs-dismiss="modal">Close</bs-button>
        <bs-button btn-style="Primary">Approve</bs-button>
    </bs-modal-footer>
</bs-modal>
            

Vertically centered

Set centered="true" to vertically center the dialog. Centering can be combined with scrollable="true" for tall body content.

aspnet

<bs-button btn-style="Primary" outline="true" data-bs-toggle="modal" data-bs-target="#centeredScrollableDocsModal">Vertically centered scrollable modal</bs-button>
<bs-modal id="centeredScrollableDocsModal" dialog-id="centeredScrollableDocsModalDialog" fade="true" centered="true" scrollable="true">
    <bs-modal-header modal-title="Vertically centered"><bs-close-button data-bs-dismiss="modal" aria-label="Close" /></bs-modal-header>
    <bs-modal-body>
        <bs-p>This centered modal is also scrollable, matching Bootstrap's combined centered and scrollable pattern.</bs-p>
    </bs-modal-body>
    <bs-modal-footer>
        <bs-button btn-style="Secondary" data-bs-dismiss="modal">Close</bs-button>
        <bs-button btn-style="Primary">Save changes</bs-button>
    </bs-modal-footer>
</bs-modal>
            

Tooltips and popovers

Tooltips and popovers can be placed inside modals. Set their container to the modal body or the document body when clipping or stacking context needs to be controlled.

aspnet

<bs-button btn-style="Secondary" data-bs-toggle="modal" data-bs-target="#tipPopoverDocsModal">Open tooltip modal</bs-button>
<bs-modal id="tipPopoverDocsModal" dialog-id="tipPopoverDocsModalDialog" fade="true">
    <bs-modal-header modal-title="Tooltips and popovers">
        <bs-close-button data-bs-dismiss="modal" aria-label="Close" />
    </bs-modal-header>
    <bs-modal-body>
        <bs-button btn-style="Secondary">
            Popover in a modal
            <bs-popover title="Popover title" container="body">Popover content inside the modal.</bs-popover>
        </bs-button>
    </bs-modal-body>
</bs-modal>
            

Using the grid

Use the grid inside bs-modal-body just as you would inside any other container. The body provides the padded region; nested rows and columns control the internal layout.

aspnet

<bs-button btn-style="Primary" outline="true" data-bs-toggle="modal" data-bs-target="#gridDocsModal">Grid modal</bs-button>
<bs-modal id="gridDocsModal" dialog-id="gridDocsModalDialog" fade="true" size="Large">
    <bs-modal-header modal-title="Grids in modals"><bs-close-button data-bs-dismiss="modal" aria-label="Close" /></bs-modal-header>
    <bs-modal-body>
        <bs-container container-type="Fluid">
            <bs-row x-gutter="Default3" y-gutter="Default3">
                <bs-div span-md="Four"><bs-div borders="All" border-rounding="All" padding="Default3">.col-md-4</bs-div></bs-div>
                <bs-div span-md="Four" start-margin="Auto"><bs-div borders="All" border-rounding="All" padding="Default3">.col-md-4 .ms-auto</bs-div></bs-div>
            </bs-row>
        </bs-container>
    </bs-modal-body>
</bs-modal>
            

Varying modal content

Use trigger data when the same modal should show content for different records. The BCL helper owns the modal markup; the trigger supplies the record metadata.

aspnet

<bs-div display="Flex" flex-wrap="Wrap" gap="Default2">
    <bs-button btn-style="Primary" data-bs-toggle="modal" data-bs-target="#varyingDocsModal" data-bs-whatever="alpha" onclick="document.getElementById('varying-recipient').value = this.getAttribute('data-bs-whatever') ?? ''">Open for alpha</bs-button>
    <bs-button btn-style="Primary" data-bs-toggle="modal" data-bs-target="#varyingDocsModal" data-bs-whatever="beta" onclick="document.getElementById('varying-recipient').value = this.getAttribute('data-bs-whatever') ?? ''">Open for beta</bs-button>
</bs-div>
<bs-modal id="varyingDocsModal" dialog-id="varyingDocsModalDialog" fade="true">
    <bs-modal-header modal-title="New message">
        <bs-close-button data-bs-dismiss="modal" aria-label="Close" />
    </bs-modal-header>
    <bs-modal-body>
        <bs-input id="varying-recipient" value="Set from the trigger" />
    </bs-modal-body>
</bs-modal>
            

Toggle between modals

Toggle between modals by dismissing the current modal and targeting the next one from the same button.

aspnet

<bs-button btn-style="Primary" data-bs-toggle="modal" data-bs-target="#toggleFirstDocsModal">Open first modal</bs-button>
<bs-modal id="toggleFirstDocsModal" dialog-id="toggleFirstDocsModalDialog" fade="true">
    <bs-modal-header modal-title="First modal"><bs-close-button data-bs-dismiss="modal" aria-label="Close" /></bs-modal-header>
    <bs-modal-body>Show a second modal and hide this one with the button below.</bs-modal-body>
    <bs-modal-footer>
        <bs-button btn-style="Primary" data-bs-target="#toggleSecondDocsModal" data-bs-toggle="modal">Open second modal</bs-button>
    </bs-modal-footer>
</bs-modal>
            

Change animation

Modal animation can be changed by overriding Bootstrap's transform variables in site CSS while the BCL helper continues to emit the modal and fade classes.

Remove animation

aspnet

<bs-button btn-style="Primary" outline="true" data-bs-toggle="modal" data-bs-target="#noFadeDocsModal">Open instant modal</bs-button>
<bs-modal id="noFadeDocsModal" dialog-id="noFadeDocsModalDialog" fade="false">
    <bs-modal-header modal-title="No fade animation">
        <bs-close-button data-bs-dismiss="modal" aria-label="Close" />
    </bs-modal-header>
    <bs-modal-body>
        <bs-p bottom-margin="None">Set <code>fade="false"</code> to omit the transition class from the modal.</bs-p>
    </bs-modal-body>
</bs-modal>
            

Dynamic heights

When content changes while a modal is open, call Bootstrap's handleUpdate() method so the dialog can recalculate its position.

Accessibility

Every modal needs an accessible title. The BCL helper assigns the dialog structure while the header title provides the visible label. Put the close button in the header, keep destructive actions clear, and avoid opening a modal from inside another modal unless you use Bootstrap's modal toggle pattern.

When a modal contains media or long-running updates, provide equivalent text, preserve keyboard reachability, and update the modal position with handleUpdate() if dynamic content changes the dialog height.

Embedding YouTube videos

Bootstrap recommends additional JavaScript for embedded videos so playback stops when the modal closes. BCL does not provide video-specific modal behavior.

Optional sizes

Set size for small, large, or extra-large dialogs. Modal widths are responsive and still constrained by the viewport.

aspnet

<bs-button btn-style="Primary" outline="true" data-bs-toggle="modal" data-bs-target="#smallDocsModal">Small modal</bs-button>
<bs-modal id="smallDocsModal" dialog-id="smallDocsModalDialog" fade="true" size="Small">
    <bs-modal-header modal-title="Small modal"><bs-close-button data-bs-dismiss="modal" aria-label="Close" /></bs-modal-header>
    <bs-modal-body>Small dialogs keep short confirmations compact while preserving the same header and close behavior.</bs-modal-body>
</bs-modal>
            

Centered, grid, and fullscreen

Use centered for vertically centered dialogs and fullscreen when the modal should take over the viewport at all or selected breakpoints.

aspnet

<bs-button btn-style="Primary" outline="true" data-bs-toggle="modal" data-bs-target="#centeredDocsModal">Centered modal</bs-button>
<bs-modal id="centeredDocsModal" dialog-id="centeredDocsModalDialog" fade="true" centered="true">
    <bs-modal-header modal-title="Vertically centered"><bs-close-button data-bs-dismiss="modal" aria-label="Close" /></bs-modal-header>
    <bs-modal-body>Centered dialogs keep short confirmation flows visually balanced.</bs-modal-body>
</bs-modal>
            

Usage

Via data attributes

Use data-bs-toggle="modal" and data-bs-target on a trigger element to open a BCL modal. Use data-bs-dismiss="modal" on close controls.

Toggle

aspnet

<bs-button btn-style="Primary" data-bs-toggle="modal" data-bs-target="#docsModal">Launch modal</bs-button>
        

Dismiss

aspnet

<bs-button btn-style="Secondary" data-bs-dismiss="modal">Close</bs-button>
        

Via JavaScript

Use Bootstrap's modal instance APIs when the workflow needs imperative show, hide, or update behavior.

javascript

const myModal = new bootstrap.Modal(document.getElementById('docsModal'))
myModal.show()
        

Options

  • backdrop maps to Bootstrap backdrop behavior, including static backdrops.
  • keyboard controls Escape-key dismissal.
  • focus remains a Bootstrap JavaScript option and is not exposed as a BCL modal helper attribute.

Methods

Bootstrap exposes show(), hide(), toggle(), handleUpdate(), and dispose() on modal instances.

Passing options

javascript

const myModal = new bootstrap.Modal('#docsModal', {
keyboard: false
})
        

Events

Modal lifecycle events include show.bs.modal, shown.bs.modal, hide.bs.modal, hidden.bs.modal, and hidePrevented.bs.modal.

CSS variables

Bootstrap exposes modal CSS variables for dialog sizing, padding, colors, borders, shadows, and backdrop behavior. BCL emits the modal structure while site styles own theme-level customization.

Sass variables

Bootstrap's Sass variables define modal dimensions, transitions, z-index behavior, backdrop opacity, and fullscreen breakpoint generation.

Sass loops

Bootstrap generates responsive fullscreen modal variants from its breakpoint map. BCL exposes fullscreen options where the helper surface supports those variants.