HTML Popover API 完整教學:不用 JavaScript 也能做彈跳框
快速解答
在觸發元素加上 popovertarget 屬性,目標元素加上 popover 屬性,不需要 JavaScript 就能開關彈跳框。瀏覽器自動處理點擊外部關閉、Esc 鍵、無障礙焦點管理。
Popover API 是什麼?跟 dialog 差在哪?
以前要做彈跳框,不管是 tooltip、dropdown 還是通知,都要:
- 手動切換
display: none / block - 監聽點擊外部關閉
- 自己疊 z-index 讓它顯示在最上層
- 加 aria 屬性處理無障礙
Popover API 把這些全部變成瀏覽器原生行為,一個屬性搞定。
跟 <dialog> 的差異很明確:
<dialog> | popover | |
|---|---|---|
| 用途 | Modal 強制互動 | 彈跳框非阻斷 |
| 背景 | 鎖定,無法操作 | 可繼續操作 |
| 使用場景 | 確認框、表單、警告 | tooltip、dropdown、通知 |
支援率:Chrome 114+、Safari 17+、Firefox 125+,目前全球約 93%,可以放心用在正式專案。
基本語法:一行 HTML 就夠
最簡單的寫法,完全不需要 JavaScript:
<button popovertarget="my-tip">顯示說明</button>
<div id="my-tip" popover>
這是彈跳框內容
</div>popovertarget:指向目標的 id,點擊時觸發開關popover:標記這個元素是彈跳框,預設等同popover="auto"
瀏覽器自動處理:
- 點擊外部關閉
- Esc 鍵關閉
- 顯示在最上層(Top Layer,不受 z-index 影響)
- 無障礙屬性(aria-expanded、aria-controls)
基本 Popover 開關
這是 Popover 彈跳框,點擊外部或按 Esc 可關閉。完全不需要 JavaScript。
auto vs manual:兩種行為模式
popover 有兩種模式:
<!-- auto:點外部自動關閉(預設) -->
<div id="tip-auto" popover>內容</div>
<!-- manual:只能用 JS 或按鈕控制 -->
<div id="tip-manual" popover="manual">內容</div>auto 模式的特性:
- 點擊外部自動關閉
- 同時只能開一個(開新的會關掉舊的)
- Esc 鍵可關閉
manual 模式的特性:
- 點擊外部不關閉
- 可以同時開多個
- 需要自己控制關閉
大部分場景用 auto 就好,manual 適合通知 toast 或需要堆疊的情況。
auto vs manual 行為對比
auto 模式:點這個框外面就會關閉。
manual 模式:點外面不會關閉,需要按按鈕。
用 JavaScript 控制 Popover
不用觸發按鈕,也可以用 JavaScript 控制:
const popover = document.getElementById('my-popover');
popover.showPopover(); // 顯示
popover.hidePopover(); // 隱藏
popover.togglePopover(); // 切換監聽開關事件:
popover.addEventListener('toggle', (e) => {
if (e.newState === 'open') {
console.log('popover 開啟了');
} else {
console.log('popover 關閉了');
}
});這在做通知系統時特別好用——manual 模式加上 toggle 事件,可以做出自動消失的 toast 通知。
自動消失的 Toast 通知
點擊後出現通知,3 秒自動消失
✓ 資料已成功儲存!
搭配 CSS 做進場動畫
Popover 預設出現沒有動畫,但搭配 :popover-open 和 @starting-style 可以做純 CSS 動畫:
[popover] {
opacity: 0;
transform: translateY(8px);
transition: opacity 0.25s ease, transform 0.25s ease,
display 0.25s allow-discrete,
overlay 0.25s allow-discrete;
}
[popover]:popover-open {
opacity: 1;
transform: translateY(0);
}
@starting-style {
[popover]:popover-open {
opacity: 0;
transform: translateY(8px);
}
}display 和 overlay 的 allow-discrete 是關鍵——讓 popover 在消失時也有動畫,而不是瞬間消失。
帶進場 / 離場動畫的 Dropdown
注意開啟和關閉都有動畫
::backdrop 與樣式化
跟 <dialog> 一樣,popover="auto" 也有 ::backdrop,但預設是透明的。你可以加上半透明遮罩:
[popover]::backdrop {
background: rgba(0, 0, 0, 0.2);
}另外,可以用 :popover-open 偽類針對開啟狀態做樣式:
/* 觸發按鈕在 popover 開啟時的樣式 */
button:has(+ [popover]:popover-open) {
background: #e0e7ff;
} 常見問題
Q:Popover 和 dialog 什麼時候用哪個?
- 需要強制使用者互動(確認、填表單)→
<dialog showModal()> - 不阻斷背景操作的彈跳框(提示、選單、通知)→
popover
Q:可以用 CSS 控制 Popover 的位置嗎?
預設 popover 出現在螢幕中央。要精確定位,可以搭配 CSS Anchor Positioning(anchor-name / position-anchor),但這個功能目前只有 Chrome 支援,通用方案還是用 JavaScript 計算位置。
Q:舊瀏覽器怎麼辦?
if (!HTMLElement.prototype.showPopover) {
// 用 dialog 或自訂邏輯替代
}目前 93% 支援率,視專案需求決定是否需要 polyfill。
總結
Popover API 填補了一個長久以來的空缺——介於完全自訂和 dialog 強制 Modal 之間的原生彈跳框。
適合用的場景:
- Tooltip / 說明提示:hover 或點擊顯示額外資訊
- Dropdown 選單:帳號、設定、篩選選項
- Toast 通知:操作成功、錯誤提示
- 浮動工具面板:顏色選擇器、格式工具列
不適合用的場景:
- 需要使用者必須回應的確認框 → 用
<dialog> - 複雜表單彈窗 → 用
<dialog>
對新專案來說,Popover API 應該是做彈跳框的預設選擇,不再需要依賴 Bootstrap dropdown 或自己從零刻了。