使用 Popover API

Popover API 為開發者提供了一種標準、一致、靈活的機制,用於在其他頁面內容之上顯示彈出式內容。彈出式內容可以透過 HTML 屬性宣告式地控制,也可以透過 JavaScript 控制。本文提供了使用其所有功能的詳細指南。

建立宣告式彈出框

最簡單的形式是,透過將 popover 屬性新增到要包含彈出內容元素中來建立彈出框。還需要一個 id 來將彈出框與其控制元件關聯起來。

html
<div id="mypopover" popover>Popover content</div>

注意:不帶值設定 popover 屬性等同於設定 popover="auto"

新增此屬性會導致元素在頁面載入時透過設定 display: none 而隱藏。要顯示/隱藏彈出框,您需要新增至少一個控制按鈕(也稱為彈出框呼叫者)。您可以透過為其提供 popovertarget 屬性來將 <button>(或 type="button"<input>)設定為彈出框控制按鈕,該屬性的值應為要控制的彈出框的 ID。

html
<button popovertarget="mypopover">Toggle the popover</button>
<div id="mypopover" popover>Popover content</div>

預設行為是按鈕為切換按鈕 — 反覆按下它將在顯示和隱藏之間切換彈出框。

如果您想更改該行為,可以使用 popovertargetaction 屬性 — 該屬性的值為 "hide""show""toggle"。例如,要建立單獨的顯示和隱藏按鈕,您可以這樣做:

html
<button popovertarget="mypopover" popovertargetaction="show">
  Show popover
</button>
<button popovertarget="mypopover" popovertargetaction="hide">
  Hide popover
</button>
<div id="mypopover" popover>Popover content</div>

您可以在我們的基本宣告式彈出框示例)中檢視前面的程式碼片段如何渲染。

注意:如果省略 popovertargetaction 屬性,"toggle" 將是控制按鈕執行的預設操作。

當彈出框顯示時,它會移除 display: none 並被放置到頂層,因此它將位於所有其他頁面內容之上。

commandcommandfor

commandforcommand 屬性提供了與 popovertargetpopovertargetaction 非常相似的功能,但設計更為通用,旨在提供彈出框命令之外的其他功能,包括自定義命令。

前面的程式碼片段可以這樣重寫:

html
<button commandfor="mypopover" command="show-popover">Show popover</button>
<button commandfor="mypopover" command="hide-popover">Hide popover</button>
<div id="mypopover" popover>Popover content</div>

自動狀態和“輕量級關閉”

當如上所示設定了 popoverpopover="auto" 的彈出框元素時,它就被認為是具有自動狀態。關於自動狀態需要注意的兩個重要行為是:

  • 彈出框可以“輕量級關閉” — 這意味著您可以透過單擊彈出框外部來隱藏它。
  • 彈出框也可以使用瀏覽器特定的機制(例如按 Esc 鍵)關閉。
  • 通常,一次只能顯示一個 auto 彈出框 — 在一個彈出框已顯示時顯示第二個彈出框將隱藏第一個。此規則的例外情況是當您有巢狀的自動彈出框時。有關更多詳細資訊,請參閱巢狀彈出框部分。

注意:popover="auto" 彈出框也會透過文件中其他元素的成功 HTMLDialogElement.showModal()Element.requestFullscreen() 呼叫而關閉。但是請記住,在已顯示的彈出框上呼叫這些方法將導致失敗,因為這些行為在已顯示的彈出框上沒有意義。但是,您可以在具有 popover 屬性但當前未顯示的元素上呼叫它們。

當您只想一次顯示一個彈出框時,自動狀態很有用。也許您有多個教學 UI 訊息要顯示,但不希望顯示變得雜亂和令人困惑,或者您正在顯示狀態訊息,其中新狀態會覆蓋任何以前的狀態。

您可以在我們的多個自動彈出框示例)中檢視上述行為的實際應用。嘗試在顯示彈出框後輕量級關閉它們,並檢視當您嘗試同時顯示兩者時會發生什麼。

彈出框輔助功能

當透過 popovertarget 屬性在彈出框及其控制元件(呼叫者)之間建立關係時,API 會自動對環境進行另外兩項更改,以使鍵盤和輔助技術 (AT) 使用者更容易與彈出框互動:

  • 當彈出框顯示時,鍵盤焦點導航順序會更新,以便彈出框在序列中緊隨其後:例如,當按下按鈕顯示彈出框時,彈出框內的任何按鈕將是選項卡順序中的下一個(透過按 Tab 鍵聚焦)。相反,當透過鍵盤關閉彈出框時(通常透過 Esc 鍵),焦點會移回呼叫者。
  • 為了讓螢幕閱讀器等 AT 理解呼叫者和彈出框之間的關係,它們之間建立了隱式的 aria-detailsaria-expanded 關係。

以這種方式在彈出框與其控制元件之間建立關係還會在這兩者之間建立隱式錨點引用 — 有關更多詳細資訊,請參閱彈出框錨點定位

設定彈出框-呼叫者關係的其他方式

除了使用 popovertarget 屬性之外,您還可以透過其他方式設定彈出框-呼叫者關係:

  • 使用 HTMLElement.showPopover()HTMLElement.togglePopover() 方法的 source 選項。請記住,在這種情況下,只進行了焦點導航順序更改,而不是隱式的 ARIA 關係。這是因為 source 選項可以設定為任何型別的元素,而不僅僅是 <button> 元素,並且無法保證這種關係有意義。
  • <select> 元素及其下拉選擇器之間,當透過 appearance 屬性 base-select 值選擇啟用可定製選擇元素功能時。在這種情況下,兩者之間會建立隱式的彈出框-呼叫者關係。

使用手動彈出框狀態

自動狀態的另一種選擇是手動狀態,透過在您的彈出框元素上設定 popover="manual" 來實現。

html
<div id="mypopover" popover="manual">Popover content</div>

在這種狀態下:

  • 彈出框不能“輕量級關閉”,儘管宣告式顯示/隱藏/切換按鈕(如前所述)仍然有效。
  • 可以同時顯示多個獨立的彈出框。

您可以在我們的多個手動彈出框示例)中檢視此行為的實際應用。

beforetoggletoggle 事件

您可以使用 beforetoggletoggle 事件來響應彈出框的顯示或隱藏。

  • beforetoggle 在彈出框顯示或隱藏之前觸發。例如,這可以用於阻止彈出框顯示或隱藏(使用 Event.preventDefault()),為彈出框新增動畫類以進行動畫處理,或在使用後清除彈出框的狀態。
  • toggle 在彈出框顯示或隱藏之後觸發。這通常用於在彈出框切換狀態更改時執行其他程式碼。

這兩個事件都具有 ToggleEvent 事件物件。除了從預設 Event 物件繼承的功能外,此事件還具有以下功能:

  • oldStatenewState 屬性指示彈出框剛剛從哪個狀態轉換到哪個狀態,允許您專門響應彈出框的開啟或關閉。
  • source 屬性包含對啟動切換的 HTML 彈出框控制元素的引用,允許您根據哪個控制元件啟動了切換來執行不同的程式碼以響應切換事件。

典型用法可能如下所示:

js
const popover = document.getElementById("mypopover");

popover.addEventListener("toggle", (e) => {
  console.log(e.newState);
});

有關更多資訊和示例,請參閱前面的參考連結。

透過 JavaScript 顯示彈出框

您還可以使用 JavaScript API 控制彈出框。

HTMLElement.popover 屬性可用於獲取或設定 popover 屬性。這可用於透過 JavaScript 建立彈出框,也可用於功能檢測。例如:

js
function supportsPopover() {
  return Object.hasOwn(HTMLElement.prototype, "popover");
}

類似地:

將這三者結合起來,您可以以程式設計方式設定彈出框及其控制按鈕,如下所示:

js
const popover = document.getElementById("mypopover");
const toggleBtn = document.getElementById("toggleBtn");

const keyboardHelpPara = document.getElementById("keyboard-help-para");

const popoverSupported = supportsPopover();

if (popoverSupported) {
  popover.popover = "auto";
  toggleBtn.popoverTargetElement = popover;
  toggleBtn.popoverTargetAction = "toggle";
} else {
  toggleBtn.style.display = "none";
}

您還有幾種方法可以控制顯示和隱藏:

例如,您可能希望透過單擊按鈕或按鍵盤上的特定鍵來切換幫助彈出框的顯示和關閉。第一個可以透過宣告式實現,或者您可以使用如上所示的 JavaScript 來實現。

對於第二個,您可以建立一個事件處理程式,程式設計兩個單獨的鍵 — 一個用於開啟彈出框,一個用於再次關閉它。

js
document.addEventListener("keydown", (event) => {
  if (event.key === "h") {
    if (popover.matches(":popover-open")) {
      popover.hidePopover();
    }
  }

  if (event.key === "s") {
    if (!popover.matches(":popover-open")) {
      popover.showPopover();
    }
  }
});

此示例使用 Element.matches() 以程式設計方式檢查彈出框當前是否正在顯示。:popover-open 偽類僅匹配當前正在顯示的彈出框。這對於避免嘗試顯示已顯示的彈出框或隱藏已隱藏的彈出框時丟擲的錯誤非常重要。

或者,您可以程式設計一個鍵來顯示和隱藏彈出框,如下所示:

js
document.addEventListener("keydown", (event) => {
  if (event.key === "h") {
    popover.togglePopover();
  }
});

請參閱我們的切換幫助 UI 示例)以檢視彈出框 JavaScript 屬性、功能檢測和 togglePopover() 方法的實際應用。

巢狀彈出框

有一個關於不同時顯示多個自動彈出框的規則的例外情況 — 當它們彼此巢狀時。在這種情況下,由於它們之間的關係,允許同時開啟多個彈出框。支援這種模式是為了實現巢狀彈出選單等用例。

建立巢狀彈出框有三種不同的方式:

  1. 直接 DOM 後代

    html
    <div popover>
      Parent
      <div popover>Child</div>
    </div>
    
  2. 透過呼叫/控制元素

    html
    <div popover>
      Parent
      <button popovertarget="foo">Click me</button>
    </div>
    
    <div popover id="foo">Child</div>
    
  3. 透過 anchor 屬性

    html
    <div popover id="foo">Parent</div>
    
    <div popover anchor="foo">Child</div>
    

請參閱我們的巢狀彈出框選單示例)以獲取示例。您會注意到,使用了相當多的事件處理程式來在滑鼠和鍵盤訪問期間適當地顯示和隱藏子彈出框,並在從任一選單中選擇選項時隱藏兩個選單。根據您處理新內容載入的方式,無論是在 SPA 還是多頁網站中,其中一些或所有這些可能都不需要,但它們已包含在此演示中用於說明目的。

使用“提示”彈出框狀態

您可以建立第三種類型的彈出框 — 提示彈出框,透過在您的彈出框元素上設定 popover="hint" 來指定。hint 彈出框在顯示時不會關閉 auto 彈出框,但會關閉其他 hint 彈出框。它們可以輕量級關閉並響應關閉請求。

這對於以下情況很有用:例如,您有可以按下以顯示 UI 彈出框的工具欄按鈕,但您還希望在滑鼠懸停在按鈕上時顯示工具提示,而不會關閉 UI 彈出框。

hint 彈出框傾向於響應非點選 JavaScript 事件(例如 mouseover/mouseoutfocus/blur)進行顯示和隱藏。單擊按鈕以開啟 hint 彈出框將導致開啟的 auto 彈出框輕量級關閉。

請參閱我們的彈出框提示演示),獲取一個行為完全如上所述的示例。該演示具有一個按鈕欄;按下時,按鈕會顯示 auto 彈出子選單,其中可以進一步選擇選項。但是,當滑鼠懸停或聚焦時,按鈕還會顯示工具提示(hint 彈出框),以讓使用者瞭解每個按鈕的作用,這些工具提示不會隱藏當前顯示的子選單。

在下面的部分中,我們將詳細介紹程式碼的所有重要部分。

注意:可以hint 彈出框與 manual 彈出框一起使用,儘管這樣做的理由不多。它們旨在規避 auto 彈出框的一些限制,從而實現本節中詳述的用例。

另請注意,在不支援的瀏覽器中,popover="hint" 會回退到 popover="manual"

使用 popover="auto" 建立子選單

彈出子選單是宣告式建立的,使用 auto 彈出框。

首先,控制按鈕:

html
<section id="button-bar">
  <button popovertarget="submenu-1" popovertargetaction="toggle" id="menu-1">
    Menu A
  </button>

  <button popovertarget="submenu-2" popovertargetaction="toggle" id="menu-2">
    Menu B
  </button>

  <button popovertarget="submenu-3" popovertargetaction="toggle" id="menu-3">
    Menu C
  </button>
</section>

現在,彈出框本身:

html
<div id="submenu-1" popover="auto">
  <button>Option A</button><br /><button>Option B</button>
</div>
<div id="submenu-2" popover="auto">
  <button>Option A</button><br /><button>Option B</button>
</div>
<div id="submenu-3" popover="auto">
  <button>Option A</button><br /><button>Option B</button>
</div>

使用 popover="hint" 建立工具提示

子選單彈出框工作正常,在按下工具欄按鈕時開啟,但我們如何也在按鈕懸停/聚焦時顯示工具提示呢?首先,我們在 HTML 中建立工具提示,使用 hint 彈出框:

html
<div id="tooltip-1" class="tooltip" popover="hint">Tooltip A</div>
<div id="tooltip-2" class="tooltip" popover="hint">Tooltip B</div>
<div id="tooltip-3" class="tooltip" popover="hint">Tooltip C</div>

注意:在演示的原始碼中,工具提示巢狀在彈出框控制按鈕內。這是因為在不支援 CSS 錨點定位的瀏覽器中,它提供了更好的回退 — hint 彈出框會出現在其關聯的控制按鈕旁邊,而不是完全在其他地方。

要控制顯示/隱藏,我們需要使用 JavaScript。首先,我們使用 Document.querySelectorAll() 獲取對 hint 彈出框和控制按鈕在兩個單獨的 NodeList 中的引用:

js
const tooltips = document.querySelectorAll(".tooltip");
const btns = document.querySelectorAll("#button-bar button");

接下來,我們建立一個函式 addEventListeners(),它在給定 <button> 上設定四個事件監聽器(透過 EventTarget.addEventListener()),該按鈕透過抓取 btns NodeList 中特定索引值的 <button> 來選擇。這些函式作用於 tooltips NodeList 中相同索引值的 hint 彈出框,使我們能夠保持按鈕和工具提示同步 — 在與按鈕互動時顯示/隱藏正確的工具提示。

事件監聽器在 mouseoverfocus顯示彈出框,並在 mouseoutblur隱藏彈出框,這意味著工具提示可以透過滑鼠和鍵盤訪問。

js
function addEventListeners(i) {
  btns[i].addEventListener("mouseover", () => {
    tooltips[i].showPopover({ source: btns[i] });
  });

  btns[i].addEventListener("mouseout", () => {
    tooltips[i].hidePopover();
  });

  btns[i].addEventListener("focus", () => {
    tooltips[i].showPopover({ source: btns[i] });
  });

  btns[i].addEventListener("blur", () => {
    tooltips[i].hidePopover();
  });
}

最後,我們使用 for 迴圈遍歷 btns NodeList 中的 <buttons>,為每個按鈕呼叫 addEventListeners() 函式,以便所有按鈕都設定了所需的事件監聽器。

js
for (let i = 0; i < btns.length; i++) {
  addEventListeners(i);
}

彈出框樣式

本節介紹了一些與彈出框相關的 CSS 選擇和定位技術。

選擇彈出框

您可以使用簡單的屬性選擇器選擇所有彈出框:

css
[popover] {
  /* Declarations here */
}

或者,您可以透過在屬性選擇器中包含值來選擇特定型別的彈出框:

css
[popover="auto"] {
  /* Declarations here */
}

您可以使用 :popover-open 偽類選擇僅顯示中的彈出框:

css
:popover-open {
  /* Declarations here */
}

為彈出框背景設定樣式

::backdrop 偽元素是一個全屏元素,直接放置在頂層中顯示的彈出框元素後面,允許在需要時為彈出框後面的頁面內容新增效果。例如,您可能希望模糊彈出框後面的內容,以幫助將使用者的注意力集中在彈出框上:

css
::backdrop {
  backdrop-filter: blur(3px);
}

請參閱我們的彈出框模糊背景示例)以瞭解其渲染效果。

定位彈出框

在檢視文章開頭連結的幾個示例時,您可能已經注意到彈出框出現在視口中間,環繞其內容,並具有黑色邊框。這是預設樣式,透過 UA 樣式表中的以下規則實現:

css
[popover] {
  position: fixed;
  inset: 0;
  width: fit-content;
  height: fit-content;
  margin: auto;
  border: solid;
  padding: 0.25em;
  overflow: auto;
  color: CanvasText;
  background-color: Canvas;
}

要應用自定義大小並將彈出框定位到其他位置,您可以使用如下所示的樣式覆蓋上述樣式:

css
:popover-open {
  width: 200px;
  height: 100px;
  position: absolute;
  inset: unset;
  bottom: 5px;
  right: 5px;
  margin: 0;
}

您可以在我們的彈出框定位示例)中看到一個獨立的示例。

彈出框錨點定位

Popover API 提供了另一個有用的定位選項。如果您想相對於其呼叫者而不是視口或定位的祖先定位彈出框,您可以利用彈出框及其呼叫者具有隱式錨點引用的事實。

將任何型別的彈出框與其呼叫者關聯都會在兩者之間建立隱式錨點引用。這會使呼叫者成為彈出框的錨點元素,這意味著您可以使用 CSS 錨點定位將其相對於它進行定位。

由於彈出框和呼叫者之間的關聯是隱式的,因此不需要使用 anchor-nameposition-anchor 屬性進行顯式關聯。但是,您仍然需要指定定位 CSS。

例如,您可以使用在嵌入屬性上設定的 anchor() 函式值和在對齊屬性上設定的 anchor-center 值的組合:

css
.my-popover {
  margin: 0;
  inset: auto;
  bottom: calc(anchor(top) + 20px);
  justify-self: anchor-center;
}

或者您可以使用 position-area 屬性:

css
.my-popover {
  margin: 0;
  inset: auto;
  position-area: top;
}

在使用 position-areaanchor() 定位彈出框時,請注意 彈出框的預設樣式可能會與您嘗試實現的位置衝突。通常的罪魁禍首是 margininset 的預設樣式,因此建議重置這些樣式,如上面的示例所示。CSS 工作組正在尋找避免需要此變通方法的方法

有關關聯錨點和定位元素以及相對於其錨點定位元素的更多詳細資訊,請參閱使用 CSS 錨點定位

注意:有關使用此隱式關聯的示例,請參閱我們的彈出框提示演示)。如果您檢視 CSS 程式碼,您會看到沒有使用 anchor-nameposition-anchor 屬性進行顯式錨點關聯。

注意:如果您想刪除隱式錨點引用以阻止彈出框錨定到其呼叫者,您可以透過將彈出框的 position-anchor 屬性設定為當前文件中不存在的錨點名稱(例如 --not-an-anchor-name)來實現。另請參閱刪除錨點關聯

彈出框動畫

彈出框在隱藏時設定為 display: none;,在顯示時設定為 display: block;,並且會被從頂層輔助功能樹中移除/新增。因此,為了使彈出框具有動畫效果,display 屬性需要是可動畫的。支援的瀏覽器會透過離散動畫型別的變體來動畫 display。具體來說,瀏覽器會在 none 和另一個 display 值之間切換,以便動畫內容在整個動畫持續時間內顯示。例如:

  • displaynone 動畫到 block(或其他可見的 display 值)時,該值將在動畫持續時間的 0% 處切換到 block,使其在整個過程中可見。
  • displayblock(或其他可見的 display 值)動畫到 none 時,該值將在動畫持續時間的 100% 處切換到 none,使其在整個過程中可見。

注意:在使用 CSS 過渡進行動畫時,需要設定 transition-behavior: allow-discrete 才能啟用上述行為。在使用 CSS 動畫進行動畫時,上述行為是預設可用的;不需要等效的步驟。

過渡彈窗

當使用 CSS 過渡動畫彈出框時,需要以下功能:

@starting-style @規則

為彈出框上設定的屬性提供一組起始值,這些屬性在彈出框首次顯示時進行過渡。這是為了避免意外行為。預設情況下,CSS 過渡僅在可見元素上的屬性從一個值更改為另一個值時發生;它們不會在元素的首次樣式更新時觸發,也不會在 display 型別從 none 更改為另一種型別時觸發。

display 屬性

display 新增到過渡列表中,以便彈出框在過渡期間保持 display: block(或另一個可見的 display 值),確保其他過渡可見。

overlay 屬性

在過渡列表中包含 overlay 以確保彈出框從頂層移除的操作延遲到過渡完成,再次確保過渡可見。

transition-behavior 屬性

displayoverlay 過渡(或在 transition 簡寫)上設定 transition-behavior: allow-discrete,以啟用這兩個預設不可動畫屬性的離散過渡。

讓我們看一個例子,這樣您就可以看到它的樣子:

HTML

HTML 包含一個 <div> 元素,透過全域性 popover HTML 屬性宣告為彈出框,以及一個指定為彈出框顯示控制元件的 <button> 元素。

html
<button popovertarget="mypopover">Show the popover</button>
<div popover="auto" id="mypopover">I'm a Popover! I should animate.</div>

CSS

我們要過渡的兩個彈出框屬性是 opacitytransform。我們希望彈出框在水平方向上放大或縮小並淡入或淡出。為了實現這一點,我們為彈出框元素的隱藏狀態(使用 [popover] 屬性選擇器選擇)設定這些屬性的起始狀態,併為彈出框的顯示狀態(透過 :popover-open 偽類選擇)設定結束狀態。我們還使用 transition 屬性定義要動畫的屬性以及彈出框顯示或隱藏時的動畫持續時間。

css
html {
  font-family: "Helvetica", "Arial", sans-serif;
}

/* Transition for the popover itself */

[popover]:popover-open {
  opacity: 1;
  transform: scaleX(1);
}

[popover] {
  font-size: 1.2rem;
  padding: 10px;

  /* Final state of the exit animation */
  opacity: 0;
  transform: scaleX(0);

  transition:
    opacity 0.7s,
    transform 0.7s,
    overlay 0.7s allow-discrete,
    display 0.7s allow-discrete;
  /* Equivalent to
  transition: all 0.7s allow-discrete; */
}

/* Needs to be after the previous [popover]:popover-open rule
to take effect, as the specificity is the same */
@starting-style {
  [popover]:popover-open {
    opacity: 0;
    transform: scaleX(0);
  }
}

/* Transition for the popover's backdrop */

[popover]::backdrop {
  background-color: transparent;
  transition:
    display 0.7s allow-discrete,
    overlay 0.7s allow-discrete,
    background-color 0.7s;
  /* Equivalent to
  transition: all 0.7s allow-discrete; */
}

[popover]:popover-open::backdrop {
  background-color: rgb(0 0 0 / 25%);
}

/* The nesting selector (&) cannot represent pseudo-elements
so this starting-style rule cannot be nested */

@starting-style {
  [popover]:popover-open::backdrop {
    background-color: transparent;
  }
}

如前所述,我們還:

  • @starting-style 塊內設定 transition 的起始狀態。
  • display 新增到過渡屬性列表中,以便動畫元素在彈出框的進入和退出動畫期間可見(設定為 display: block)。沒有這個,退出動畫將不可見;實際上,彈出框只會消失。
  • overlay 新增到過渡屬性列表中,以確保將元素從頂層移除的操作延遲到動畫完成。對於此類基本動畫,其效果可能不明顯,但在更復雜的情況下,省略此屬性可能導致元素在過渡完成之前從疊加層中移除。
  • 在上述過渡中的兩個屬性上都設定了 allow-discrete,以啟用離散過渡

您會注意到,我們還在彈出框開啟時,彈出框後面出現的 ::backdrop 上添加了過渡,提供了一個漂亮的變暗動畫。

結果

程式碼渲染如下:

備註: 因為 popover 每次顯示時都會從 display: none 變為 display: block,所以每次進入過渡發生時,popover 都會從其 @starting-style 樣式過渡到其 [popover]:popover-open 樣式。當 popover 關閉時,它會從其 [popover]:popover-open 狀態過渡到預設的 [popover] 狀態。

在這種情況下,進入和退出時的樣式過渡可能會有所不同。請參閱我們的何時使用起始樣式的演示示例以證明這一點。

彈出框關鍵幀動畫

使用 CSS 關鍵幀動畫動畫彈出框時,有一些不同之處需要注意:

  • 您不提供 @starting-style;您在關鍵幀中包含“to”和“from”的 display 值。
  • 您不會顯式啟用離散動畫;關鍵幀中沒有與 allow-discrete 等效的屬性。
  • 您也不需要在關鍵幀中設定 overlaydisplay 動畫處理彈出框從顯示到隱藏的動畫。

讓我們看一個例子。

HTML

HTML 包含一個宣告為彈出框的 <div> 元素,以及一個指定為彈出框顯示控制元件的 <button> 元素。

html
<button popovertarget="mypopover">Show the popover</button>
<div popover="auto" id="mypopover">I'm a Popover! I should animate.</div>

CSS

我們定義了關鍵幀,它們指定了所需的進入和退出動畫,以及僅用於背景的進入動畫。請注意,無法動畫背景淡出 — 當彈出框關閉時,背景會立即從 DOM 中移除,因此沒有什麼可以動畫的。

css
html {
  font-family: "Helvetica", "Arial", sans-serif;
}

[popover] {
  font-size: 1.2rem;
  padding: 10px;
  animation: fade-out 0.7s ease-out;
}

[popover]:popover-open {
  animation: fade-in 0.7s ease-out;
}

[popover]:popover-open::backdrop {
  animation: backdrop-fade-in 0.7s ease-out forwards;
}

/* Animation keyframes */

@keyframes fade-in {
  0% {
    opacity: 0;
    transform: scaleX(0);
  }

  100% {
    opacity: 1;
    transform: scaleX(1);
  }
}

@keyframes fade-out {
  0% {
    opacity: 1;
    transform: scaleX(1);
    /* display needed on the closing animation to keep the popover
    visible until the animation ends */
    display: block;
  }

  100% {
    opacity: 0;
    transform: scaleX(0);
    /* display: none not required here because it is the default value
    for a closed popover, but including it so the behavior is clear */
    display: none;
  }
}

@keyframes backdrop-fade-in {
  0% {
    background-color: transparent;
  }

  100% {
    background-color: rgb(0 0 0 / 25%);
  }
}

結果

程式碼渲染如下: