Skip to main content Skip to docs navigation
View on GitHub

互動視窗 (Modal)

使用 Bootstrap JavaScript 的互動視窗插件來增加一個對話視窗,用於用戶提示、燈箱或完整的自訂內容。

六角學院的 Bootstrap 5 課程上線囉,立即與萬人一同學習最專業、最深入的 Bootstrap 5 課程。

立即上課去

如何運作

在開始使用 Bootstrap 互動視窗之前,請務必閱讀以下內容,因為選單項目在近期內有修改。

  • 互動視窗是用 HTML、CSS 和 JavaScript 構建的。 它們位於文件中任何其他內容之上,並從 <body> 中刪除滾動,以便互動視窗的內容滾動。
  • 點擊互動視窗 “backdrop” 將自動關閉互動視窗。
  • Bootstrap 一次只支援一個互動視窗。不支援巢狀互動視窗,因為我們認為巢狀互動視窗用戶體驗不佳。
  • 互動視窗使用 position: fixed ,在渲染呈現上會有點特別。盡可能將您的互動視窗 HTML 放置在頂級位置,以避免其他元素的潛在干擾。在另一個固定元素中內加入一個 .modal 的時候,你可能會遇到問題。
  • 由於 position: fixed,在移動設備上使用互動視窗有一些附加說明。有關詳細資訊,請參閱 我們的瀏覽器支援
  • 依據 HTML5 定義語義的方式,autofocus HTML 屬性 對 Bootstrap 互動視窗沒有影響。 要達到同樣的效果,請使用一些自訂 JavaScript:
var myModal = document.getElementById('myModal')
var myInput = document.getElementById('myInput')

myModal.addEventListener('shown.bs.modal', function () {
  myInput.focus()
})
該元件的動畫效果取決於 prefers-reduced-motion media queries。請參考 reduced motion section of our accessibility documentation

繼續閱讀 demos 和使用指南。

範例

下面是一個 靜態 動態視窗範例(意思是它的 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>

完整範例

通過點擊下面的按鈕切換動態視窗呈現。它將從頁面頂部向下滑動並淡入。

<!-- 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">
        <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
        <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">
        <h5 class="modal-title" id="staticBackdropLabel">Modal title</h5>
        <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 來創建一個 body 可滾動互動視窗。

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

垂直置中

加入 .modal-dialog-centered.modal-dialog 來使互動視窗垂直置中。

<!-- 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>

工具提示和彈出提示框

Tooltipspopovers 可以根據需要放置在動態視窗。 當動態視窗關閉時,其中的任何工具提示和插件也將自動關閉。

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

使用網格

透過在 .modal-body 中加入 .container-fluid 在互動視窗中使用 Bootstrap 網格系統。然後像其他任何地方一樣使用正常的網格系統 class。

<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-* 屬性 依據點擊按鈕來更改動態視窗的內容。

下面是 HTML 和 JavaScript 的範例。 有關 relatedTarget 的詳細資訊,請參閱 互動視窗的事件

<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">
        <h5 class="modal-title" id="exampleModalLabel">New message</h5>
        <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>
var exampleModal = document.getElementById('exampleModal')
exampleModal.addEventListener('show.bs.modal', function (event) {
  // Button that triggered the modal
  var button = event.relatedTarget
  // Extract info from data-bs-* attributes
  var 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.
  var modalTitle = exampleModal.querySelector('.modal-title')
  var modalBodyInput = exampleModal.querySelector('.modal-body input')

  modalTitle.textContent = 'New message to ' + recipient
  modalBodyInput.value = recipient
})

在互動視窗間切換

通過設定 data-bs-targetdata-bs-toggle 屬性在多個互動視窗中切換。例如,你可以從已經打開的登錄視窗中切換為重新設定密碼的視窗。請注意不能同時打開多個互動視窗—這種方法只是在兩個單獨的互動視窗之間切換。

Open first modal
<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">
        <h5 class="modal-title" id="exampleModalToggleLabel">Modal 1</h5>
        <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">
        <h5 class="modal-title" id="exampleModalToggleLabel2">Modal 2</h5>
        <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>
<a class="btn btn-primary" data-bs-toggle="modal" href="#exampleModalToggle" role="button">Open first modal</a>

Change animation

$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",因為 bootstrap 的 JavaScript 已經有添加了。

嵌入 YouTube 影片

在互動視窗上嵌入 YouTube 影片需要額外的 JavaScript 以自動停止重播或其他更多功能。有關詳細資訊,請參閱 Stack Overflow 的文章

大小選項

互動視窗有三個可選的大小,透過 .modal-dialog 上的 modifier Class 啟用。 這些尺寸會在某些中斷點調整,以避免在較窄的 viewport 上出現水平捲軸。

Size Class Modal max-width
Small .modal-sm 300px
Default None 500px
Large .modal-lg 800px
Extra large .modal-xl 1140px

預設的互動視窗沒有 “medium” 這個類別的大小。

<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 Below 576px
.modal-fullscreen-md-down Below 768px
.modal-fullscreen-lg-down Below 992px
.modal-fullscreen-xl-down Below 1200px
.modal-fullscreen-xxl-down Below 1400px
<!-- Full screen modal -->
<div class="modal-dialog modal-fullscreen-sm-down">
  ...
</div>

Sass

Variables

$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:                  $white;
$modal-content-border-color:        rgba($black, .2);
$modal-content-border-width:        $border-width;
$modal-content-border-radius:       $border-radius-lg;
$modal-content-inner-border-radius: subtract($modal-content-border-radius, $modal-content-border-width);
$modal-content-box-shadow-xs:       $box-shadow-sm;
$modal-content-box-shadow-sm-up:    $box-shadow;

$modal-backdrop-bg:                 $black;
$modal-backdrop-opacity:            .5;
$modal-header-border-color:         $border-color;
$modal-footer-border-color:         $modal-header-border-color;
$modal-header-border-width:         $modal-content-border-width;
$modal-footer-border-width:         $modal-header-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-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);

Loop

響應式滿版互動視窗 是通過 $breakpoints map 和 scss/_modal.scss 中的 loop 生成的。

@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 {
        @include border-radius(0);
      }

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

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

用法

互動視窗插件透過資料屬性或 JavaScript 切換您隱藏的內容。它將 .modal-open 加到 <body> 以覆寫預設的滾動行為,並生成一個 .modal-backdrop 來提供點擊區域,以便在點擊動態視窗外面時移除顯示的動態視窗。

透過資料屬性

Toggle

不需要撰寫 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>

Dismiss

Dismissal can be achieved with the data attribute on a button within the modal as demonstrated below:

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

or on a button outside the modal using the data-bs-target as demonstrated below:

<button type="button" class="btn-close" data-bs-dismiss="modal" data-bs-target="#my-modal" aria-label="Close"></button>
雖然兩種方式都支援關閉互動視窗,但請記住從互動視窗外部關閉與 the WAI-ARIA modal dialog design pattern 不匹配。這樣做的風險由您自己承擔。

透過 JavaScript

用一行 JavaScript 創建一個互動視窗:

var myModal = new bootstrap.Modal(document.getElementById('myModal'), options)

選項

可以透過資料屬性或 JavaScript 傳遞選項。對於資料屬性,將選項名稱附加到 data-bs,如 data-bs-backdrop=""

Name Type Default Description
backdrop boolean or the string 'static' true 包括一個 modal-backdrop 元素。或是,為不會在點擊時關閉互動視窗的背景指定 static
keyboard boolean true 按下 ESC 鍵時關閉互動視窗。
focus boolean true 初始化時將 focus 放在互動視窗上。

方法

Asynchronous methods and transitions

All API methods are asynchronous and start a transition. They return to the caller as soon as the transition is started but before it ends. In addition, a method call on a transitioning component will be ignored.

See our JavaScript documentation for more information.

傳遞選項

將你的內容啟用為互動視窗,接受一個選擇性的 object 選項。

var myModal = new bootstrap.Modal(document.getElementById('myModal'), {
  keyboard: false
})

toggle

手動切換動態視窗。在動態視窗實際顯示或隱藏之前返回給調用者(即在 shown.bs.modalhidden.bs.modal 事件發生之前)。

myModal.toggle()

show

手動打開動態視窗。在動態視窗實際顯示之前返回給調用者(即在 shown.bs.modal 事件發生之前)。

myModal.show()

此外,你可以將 DOM 元素作為可在互動視窗事件中接收的參數 (作為 relatedTarget 屬性) 傳遞。

var modalToggle = document.getElementById('toggleMyModal') // relatedTarget
myModal.show(modalToggle)

hide

手動隱藏動態視窗。在動態視窗實際隱藏之前返回給調用者(即在 hidden.bs.modal 事件發生之前)。

myModal.hide()

handleUpdate

如果動態視窗在打開狀態(比如在出現捲軸的情況下)高度改變,則重新調整動態視窗的位置。

myModal.handleUpdate()

dispose

銷毀一個元素的 Modal。(刪除 DOM 元素上儲存的資料)

myModal.dispose()

getInstance

靜態 方法,可以讓你獲取與 DOM 元素相關聯的互動視窗實例。

var myModalEl = document.getElementById('myModal')
var modal = bootstrap.Modal.getInstance(myModalEl) // Returns a Bootstrap modal instance

getOrCreateInstance

靜態 方法,允許獲取與 DOM 元素相關聯的互動視窗實例,或者在未初始化的情況下創建一個新實例。

var myModalEl = document.querySelector('#myModal')
var modal = bootstrap.Modal.getOrCreateInstance(myModalEl) // Returns a Bootstrap modal instance

事件

Bootstrap 的 model class 也有提供一些用於 model 功能的事件,所有相關事件都在 Model 本身被觸發(在 <div class="modal">)。

Event type Description
show.bs.modal 當呼叫 show 實例方法時,此事件會立即觸發。如果是由點擊事件觸發,被點擊的元素可作為事件的 relatedTarget 屬性。
shown.bs.modal 當呼動視窗顯示時將會觸發此事件(等待 CSS 轉換完成)。如果是由點擊事件觸發,被點擊的元素可作為事件的 relatedTarget 屬性
hide.bs.modal 當呼叫 hide 實例方法時,將會立即觸發此事件。
hidden.bs.modal 當互動視窗隱藏後將會觸發此事件(等 CSS 轉換完成)。
hidePrevented.bs.modal 當顯示互動視窗後將會觸發此事件,其背景是 static 的,model 以外的點擊或按下 esc 會被鍵盤選項、 data-bs-keyboard 設置為 false
var myModalEl = document.getElementById('myModal')
myModalEl.addEventListener('hidden.bs.modal', function (event) {
  // do something...
})