Skip to main content Skip to docs navigation

模态弹框(Modal)

使用 Bootstrap 的 JavaScript 模态插件为网站添加对话框,用于灯箱、用户通知或完全自定义的内容。

工作原理

在开始使用 Bootstrap 的模态组件之前,请务必阅读以下内容,因为我们的菜单选项最近发生了变化。

  • 模态由 HTML、CSS 和 JavaScript 构建。它们的位置高于文档中的其他内容,并从<body> 中移除滚动条,从而使模态内容可以滚动。
  • 点击模态 “背景” 将自动关闭模态。
  • Bootstrap 一次只支持一个模式窗口。我们不支持嵌套模式窗口,因为我们认为它们的用户体验很差。
  • 模态使用 position: fixed(位置:固定),有时在渲染时会有些特别。只要有可能,请将模式 HTML 放在顶层位置,以避免其他元素的潜在干扰。如果在另一个固定元素中嵌套一个 .modal,很可能会遇到问题。
  • 同样,由于position: fixed 的原因,在移动设备上使用模式也有一些注意事项。详情请参阅我们的浏览器支持文档
  • 由于 HTML5 如何定义其语义,autofocus HTML 属性 在 Bootstrap 模态中不起作用。要实现相同的效果,请使用一些自定义 JavaScript:
const myModal = document.getElementById('myModal')
const myInput = document.getElementById('myInput')

myModal.addEventListener('shown.bs.modal', () => {
  myInput.focus()
})
该组件的动画效果取决于 prefers-reduced-motion 媒体查询。请参阅我们的可访问性文档中的缩减动作部分.

请继续阅读演示和使用指南。

示例

模态组件

下面是一个 static 模态示例(即其 positiondisplay 已被覆盖)。其中包括模态页眉、模态主体(padding需要)和模态页脚(可选)。我们要求您尽可能在模态头中包含解散操作,或提供其他明确的解散操作。

<div class="modal" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal title</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <p>Modal body text goes here.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>
在上述静态示例中,我们使用了 <h5>,以避免与文档页面中的标题层次结构产生冲突。但是,从结构上讲,模式对话框代表其独立的文档/上下文,因此 .modal-title最好是 <h1>。如有必要,您可以使用 字体大小实用工具 来控制标题的外观。以下所有示例都使用了这种方法。

现场演示

点击下面的按钮,切换一个正常工作的模式演示。它将从页面顶部向下滑动并淡入。

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  Launch demo modal
</button>

<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

静态背景

当背景设置为静态时,当点击模式窗外时,模式窗不会关闭。点击下面的按钮试试。

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#staticBackdrop">
  Launch static backdrop modal
</button>

<!-- Modal -->
<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="staticBackdropLabel">Modal title</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Understood</button>
      </div>
    </div>
  </div>
</div>

滚动长内容

当模块对于用户的视口或设备来说过长时,它们会独立于页面本身滚动。请尝试下面的演示,了解我们的意思。

您还可以在 .modal-dialog中添加 .modal-dialog-scrollable,创建可滚动模态,允许滚动模态正文。

<!-- Scrollable modal -->
<div class="modal-dialog modal-dialog-scrollable">
  ...
</div>

垂直居中

.modal-dialog 中添加.modal-dialog-centered,使模态垂直居中。

<!-- Vertically centered modal -->
<div class="modal-dialog modal-dialog-centered">
  ...
</div>

<!-- Vertically centered scrollable modal -->
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
  ...
</div>

工具提示和弹出窗口

工具提示弹出窗口 可以根据需要放置在模态中。关闭模态后,模态中的工具提示和弹出窗口也会自动关闭。

<div class="modal-body">
  <h2 class="fs-5">Popover in a modal</h2>
  <p>This <button class="btn btn-secondary" data-bs-toggle="popover" title="Popover title" data-bs-content="Popover body content is set in this attribute.">button</button> triggers a popover on click.</p>
  <hr>
  <h2 class="fs-5">Tooltips in a modal</h2>
  <p><a href="#" data-bs-toggle="tooltip" title="Tooltip">This link</a> and <a href="#" data-bs-toggle="tooltip" title="Tooltip">that link</a> have tooltips on hover.</p>
</div>

使用网格

通过将.container-fluid嵌套在.modal-body中,在模态中使用 Bootstrap 网格系统。然后,像在其他地方一样使用正常的网格系统类。

<div class="modal-body">
  <div class="container-fluid">
    <div class="row">
      <div class="col-md-4">.col-md-4</div>
      <div class="col-md-4 ms-auto">.col-md-4 .ms-auto</div>
    </div>
    <div class="row">
      <div class="col-md-3 ms-auto">.col-md-3 .ms-auto</div>
      <div class="col-md-2 ms-auto">.col-md-2 .ms-auto</div>
    </div>
    <div class="row">
      <div class="col-md-6 ms-auto">.col-md-6 .ms-auto</div>
    </div>
    <div class="row">
      <div class="col-sm-9">
        Level 1: .col-sm-9
        <div class="row">
          <div class="col-8 col-sm-6">
            Level 2: .col-8 .col-sm-6
          </div>
          <div class="col-4 col-sm-6">
            Level 2: .col-4 .col-sm-6
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

可变模态内容

有一堆按钮都会触发内容略有不同的同一模态?使用 event.relatedTargetHTML data-bs-* attributes,根据点击的按钮来改变模态的内容。

下面是一个实时演示,后面是 HTML 和 JavaScript 示例。如需了解更多信息,请阅读模式事件文档,了解有关 relatedTarget 的详细信息。

html
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">Open modal for @mdo</button>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@fat">Open modal for @fat</button>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@getbootstrap">Open modal for @getbootstrap</button>

<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel">New message</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <form>
          <div class="mb-3">
            <label for="recipient-name" class="col-form-label">Recipient:</label>
            <input type="text" class="form-control" id="recipient-name">
          </div>
          <div class="mb-3">
            <label for="message-text" class="col-form-label">Message:</label>
            <textarea class="form-control" id="message-text"></textarea>
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Send message</button>
      </div>
    </div>
  </div>
</div>
const exampleModal = document.getElementById('exampleModal')
if (exampleModal) {
  exampleModal.addEventListener('show.bs.modal', event => {
    // Button that triggered the modal
    const button = event.relatedTarget
    // Extract info from data-bs-* attributes
    const recipient = button.getAttribute('data-bs-whatever')
    // If necessary, you could initiate an Ajax request here
    // and then do the updating in a callback.

    // Update the modal's content.
    const modalTitle = exampleModal.querySelector('.modal-title')
    const modalBodyInput = exampleModal.querySelector('.modal-body input')

    modalTitle.textContent = `New message to ${recipient}`
    modalBodyInput.value = recipient
  })
}

模态之间的切换

通过巧妙使用 data-bs-targetdata-bs-toggle 属性,在多个模态之间切换。例如,您可以在一个已打开的登录模态中切换密码重置模态。请注意,不能同时打开多个模态 –此方法只是在两个独立的模态之间切换。

html
<div class="modal fade" id="exampleModalToggle" aria-hidden="true" aria-labelledby="exampleModalToggleLabel" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalToggleLabel">Modal 1</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Show a second modal and hide this one with the button below.
      </div>
      <div class="modal-footer">
        <button class="btn btn-primary" data-bs-target="#exampleModalToggle2" data-bs-toggle="modal">Open second modal</button>
      </div>
    </div>
  </div>
</div>
<div class="modal fade" id="exampleModalToggle2" aria-hidden="true" aria-labelledby="exampleModalToggleLabel2" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalToggleLabel2">Modal 2</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        Hide this modal and show the first with the button below.
      </div>
      <div class="modal-footer">
        <button class="btn btn-primary" data-bs-target="#exampleModalToggle" data-bs-toggle="modal">Back to first</button>
      </div>
    </div>
  </div>
</div>
<button class="btn btn-primary" data-bs-target="#exampleModalToggle" data-bs-toggle="modal">Open first modal</button>

更改动画

$modal-fade-transform 变量决定了模态淡入动画之前.modal-dialog 的变换状态,$modal-show-transform 变量决定了模态淡入动画结束时.modal-dialog 的变换状态。

如果您想要放大动画,可以设置 $modal-fade-transform: scale(.8)

移除动画

对于只是出现而不是淡入视图的模式,请从模式标记中删除 .fade 类。

<div class="modal" tabindex="-1" aria-labelledby="..." aria-hidden="true">
  ...
</div>

动态高度

如果模态的高度在打开时发生变化,则应调用 myModal.handleUpdate() 重新调整模态的位置,以防出现滚动条。

辅助功能

请务必在 .modal中添加 aria-labelledby="..." ,引用模态标题。此外,您还可以在 .modal 中添加 aria-describedby 来描述模态对话框。请注意,您不需要添加 role="dialog" ,因为我们已经通过 JavaScript 添加了。

嵌入 YouTube 视频

在模态中嵌入 YouTube 视频需要 Bootstrap 中没有的额外 JavaScript 来自动停止播放等。更多信息,请参阅 Stack Overflow 这篇有用的帖子

可选尺寸

模态对话框有三种可选尺寸,可通过放在.modal-dialog上的修改器类获得。这些尺寸会在某些断点处启动,以避免在较窄的视口上出现水平滚动条。

Size Class Modal max-width
.modal-sm 300px
默认 None 500px
.modal-lg 800px
特大号 .modal-xl 1140px

我们默认的不带修饰符的模态是 “中等” 大小的模态。

<div class="modal-dialog modal-xl">...</div>
<div class="modal-dialog modal-lg">...</div>
<div class="modal-dialog modal-sm">...</div>

全屏模态

另一个覆盖选项是弹出一个覆盖用户视口的模式对话框,可通过放置在.modal-dialog上的修改器类来实现。

Class Availability
.modal-fullscreen Always
.modal-fullscreen-sm-down 576px
.modal-fullscreen-md-down 768px
.modal-fullscreen-lg-down 992px
.modal-fullscreen-xl-down 1200px
.modal-fullscreen-xxl-down 1400px
<!-- Full screen modal -->
<div class="modal-dialog modal-fullscreen-sm-down">
  ...
</div>

CSS

变量

Added in v5.2.0

作为 Bootstrap 不断发展的 CSS 变量方法的一部分,模态现在使用 .modal.modal-backdrop 上的本地 CSS 变量来增强实时自定义功能。CSS 变量的值通过 Sass 设置,因此仍支持 Sass 自定义。

--#{$prefix}modal-zindex: #{$zindex-modal};
--#{$prefix}modal-width: #{$modal-md};
--#{$prefix}modal-padding: #{$modal-inner-padding};
--#{$prefix}modal-margin: #{$modal-dialog-margin};
--#{$prefix}modal-color: #{$modal-content-color};
--#{$prefix}modal-bg: #{$modal-content-bg};
--#{$prefix}modal-border-color: #{$modal-content-border-color};
--#{$prefix}modal-border-width: #{$modal-content-border-width};
--#{$prefix}modal-border-radius: #{$modal-content-border-radius};
--#{$prefix}modal-box-shadow: #{$modal-content-box-shadow-xs};
--#{$prefix}modal-inner-border-radius: #{$modal-content-inner-border-radius};
--#{$prefix}modal-header-padding-x: #{$modal-header-padding-x};
--#{$prefix}modal-header-padding-y: #{$modal-header-padding-y};
--#{$prefix}modal-header-padding: #{$modal-header-padding}; // Todo in v6: Split this padding into x and y
--#{$prefix}modal-header-border-color: #{$modal-header-border-color};
--#{$prefix}modal-header-border-width: #{$modal-header-border-width};
--#{$prefix}modal-title-line-height: #{$modal-title-line-height};
--#{$prefix}modal-footer-gap: #{$modal-footer-margin-between};
--#{$prefix}modal-footer-bg: #{$modal-footer-bg};
--#{$prefix}modal-footer-border-color: #{$modal-footer-border-color};
--#{$prefix}modal-footer-border-width: #{$modal-footer-border-width};
--#{$prefix}backdrop-zindex: #{$zindex-modal-backdrop};
--#{$prefix}backdrop-bg: #{$modal-backdrop-bg};
--#{$prefix}backdrop-opacity: #{$modal-backdrop-opacity};

Sass 变量

$modal-inner-padding:               $spacer;

$modal-footer-margin-between:       .5rem;

$modal-dialog-margin:               .5rem;
$modal-dialog-margin-y-sm-up:       1.75rem;

$modal-title-line-height:           $line-height-base;

$modal-content-color:               null;
$modal-content-bg:                  var(--#{$prefix}body-bg);
$modal-content-border-color:        var(--#{$prefix}border-color-translucent);
$modal-content-border-width:        var(--#{$prefix}border-width);
$modal-content-border-radius:       var(--#{$prefix}border-radius-lg);
$modal-content-inner-border-radius: subtract($modal-content-border-radius, $modal-content-border-width);
$modal-content-box-shadow-xs:       var(--#{$prefix}box-shadow-sm);
$modal-content-box-shadow-sm-up:    var(--#{$prefix}box-shadow);

$modal-backdrop-bg:                 $black;
$modal-backdrop-opacity:            .5;

$modal-header-border-color:         var(--#{$prefix}border-color);
$modal-header-border-width:         $modal-content-border-width;
$modal-header-padding-y:            $modal-inner-padding;
$modal-header-padding-x:            $modal-inner-padding;
$modal-header-padding:              $modal-header-padding-y $modal-header-padding-x; // Keep this for backwards compatibility

$modal-footer-bg:                   null;
$modal-footer-border-color:         $modal-header-border-color;
$modal-footer-border-width:         $modal-header-border-width;

$modal-sm:                          300px;
$modal-md:                          500px;
$modal-lg:                          800px;
$modal-xl:                          1140px;

$modal-fade-transform:              translate(0, -50px);
$modal-show-transform:              none;
$modal-transition:                  transform .3s ease-out;
$modal-scale-transform:             scale(1.02);

Sass loops 循环

响应式全屏模式 是通过 $breakpoints 映射和 scss/_modal.scss 中的循环生成的。

@each $breakpoint in map-keys($grid-breakpoints) {
  $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
  $postfix: if($infix != "", $infix + "-down", "");

  @include media-breakpoint-down($breakpoint) {
    .modal-fullscreen#{$postfix} {
      width: 100vw;
      max-width: none;
      height: 100%;
      margin: 0;

      .modal-content {
        height: 100%;
        border: 0;
        @include border-radius(0);
      }

      .modal-header,
      .modal-footer {
        @include border-radius(0);
      }

      .modal-body {
        overflow-y: auto;
      }
    }
  }
}

用法

该模态插件可通过数据属性或 JavaScript 按需切换隐藏内容。它还会覆盖默认的滚动行为,并生成一个 .modal-backdrop,以便在点击模态外的内容时提供一个点击区域来取消已显示的模态。

通过数据属性

切换

无需编写 JavaScript 即可激活模态。在控制器元素(如按钮)上设置 data-bs-toggle="modal" 以及 data-bs-target="#foo"href="#foo" 以锁定要切换的特定模态。

<button type="button" data-bs-toggle="modal" data-bs-target="#myModal">Launch modal</button>

解除

如下图所示,可通过按钮上的 data-bs-dismiss 属性 modal 实现解除:

<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>

或在 modal 外的按钮上使用附加的 data-bs-target,如下所示:

<button type="button" class="btn-close" data-bs-dismiss="modal" data-bs-target="#my-modal" aria-label="Close"></button>
虽然这两种方式都支持解散模态,但请记住,从模态外部解散不符合ARIA 创作实践指南对话框(模态)模式。请自行承担风险。

通过 JavaScript

用一行 JavaScript 创建一个模态:

const myModal = new bootstrap.Modal(document.getElementById('myModal'), options)
// or
const myModalAlternative = new bootstrap.Modal('#myModal', options)

选项

由于可以通过 data 属性或 JavaScript 传递选项,因此可以在 data-bs- 中附加选项名称,如 data-bs-animation=“{value}”。通过data 属性传递选项时,请确保将选项名称的大小写类型从“camelCase”改为“kebab-case”。例如,使用 data-bs-custom-class=“beautifier” 而不是 data-bs-customClass=“beautifier”

从 Bootstrap 5.2.0 开始,所有组件都支持一个实验性预留data 属性 data-bs-config ,它可以将简单的组件配置以 JSON 字符串的形式存放。当一个元素具有data-bs-config='{“delay”:0, “title”:123}'data-bs-title=“456” 属性时,最终的title值将是456,而单独的data 属性将覆盖data-bs-config上给出的值。此外,现有的data 属性还能容纳 JSON 值,如 data-bs-delay='{“show”:0, “hide”:150}'

最终配置对象是 data-bs-configdata-bs-js object 的合并结果,其中最新给定的键值优先于其他键值。

Name Type Default Description
backdrop boolean, 'static' true 包括一个模态背景板元素。或者,指定 static,以获得点击后不会关闭模态的背景板。
focus boolean true 初始化时将焦点放在模态上。
keyboard boolean true 按下 Esc 键后关闭模态。

方法

所有 API 方法都是异步的,并且会启动一个过渡,它们会在过渡开始后、结束前返回给调用者。此外,对过渡组件的方法调用将被忽略。更多信息,请参阅 JavaScript 文档

传递选项

将内容激活为模态。接受一个可选的选项 object

const myModal = new bootstrap.Modal('#myModal', {
  keyboard: false
})
Method Description
dispose 销毁元素的模态。(删除 DOM 元素上存储的数据)
getInstance Static 方法,可以获取与 DOM 元素相关联的模态实例。
getOrCreateInstance Static 方法,可以获取与 DOM 元素相关联的模态实例,或者在未初始化的情况下创建一个新的模态实例。
handleUpdate 如果模态的高度在打开时发生变化(例如出现滚动条),可手动重新调整模态的位置。
hide 手动隐藏模态。在模态实际隐藏之前 返回给调用者(即在 hidden.bs.modal 事件发生之前)。
show 手动打开模态。在模态实际显示之前(即在 shown.bs.modal 事件发生之前)返回给调用者。此外,您还可以传递一个 DOM 元素作为参数,以便在模态事件中接收(作为 relatedTarget 属性)。(例如,const modalToggle = document.getElementById('toggleMyModal'); myModal.show(modalToggle).
toggle 手动切换模态。在模态实际显示或隐藏之前 返回给调用者(即在 shown.bs.modalhidden.bs.modal 事件发生之前)。

事件

Bootstrap 的模态类提供了一些事件,用于连接模态功能。所有模态事件都是在模态本身(即 <div class="modal">)触发的。

Event Description
hide.bs.modal 当调用 hide 实例方法时,会立即触发该事件。
hidden.bs.modal 当模态完成对用户的隐藏时(将等待 CSS 过渡完成),将触发此事件。
hidePrevented.bs.modal 该事件在模态显示、其背景为 static 且在模态外点击时触发。当按下 escape 键且 keyboard 选项设置为 false 时,也会触发该事件。
show.bs.modal 当调用 show 实例方法时,该事件立即触发。如果由点击引起,被点击的元素可作为事件的 relatedTarget 属性。
shown.bs.modal 当用户看到模态(将等待 CSS 过渡完成)时,将触发该事件。如果是由点击引起的,被点击的元素可作为事件的 relatedTarget 属性。
const myModalEl = document.getElementById('myModal')
myModalEl.addEventListener('hidden.bs.modal', event => {
  // do something...
})