HTML Popover API 怎麼用:用原生按鈕建立可關閉的浮層
做提示、篩選器或帳號選單時,很多專案會先引入一套浮層元件,然後才補定位、Esc 關閉與點擊外部關閉。若需求只是讓一段補充內容暫時浮在頁面上,HTML Popover API 已能處理這個基本互動。
直接答案是:可被使用者隨手關閉的輕量浮層用 popover="auto";必須由程式明確控制、不能點外部關閉的工具面板才用 manual。需要阻擋背景操作或要求使用者完成決策時,仍應使用 <dialog>。
最小可用範例
把 popover 放在要顯示的元素,再讓按鈕的 popovertarget 指向它的 id:
<button type="button" popovertarget="filter-help"> 篩選說明</button>
<div id="filter-help" popover> 只會顯示符合目前分類的文章。</div>沒有填值的 popover 等同 popover="auto"。瀏覽器會先把浮層隱藏;按鈕被按下後顯示,再按一次切換回隱藏。auto 浮層也可用 Esc 或點擊外部關閉,並會在開啟另一個非巢狀 auto 浮層時關閉前一個。
這種宣告式關聯比手寫 aria-expanded、document click listener 更小,但不代表可以省略語意。按鈕名稱要描述動作,浮層裡的控制項仍應有自己的 label。
auto、hint、manual 與 <dialog> 分別解決什麼
| 元件 | 適合情況 | 關閉方式 | 不適合的情況 |
|---|---|---|---|
popover="auto" | 說明、選單、非關鍵提示 | 按鈕、Esc、點外部 | 需要強制回應的確認流程 |
popover="hint" | 已開啟選單旁的輔助提示 | 關閉要求、點外部;另設離開/失焦處理 | 支援範圍尚未確認的唯一操作入口 |
popover="manual" | 開發者工具列、持續顯示的小面板 | 程式或自己的關閉按鈕 | 讀者預期可點外部收起的選單 |
<dialog> | 刪除確認、登入、需要 modal 的表單 | close()、表單或明確按鈕 | 只想展示一小段輔助內容 |
manual 不會 light dismiss,也不會因另一個 popover 出現而自動關閉。它適合已經有明確生命週期的面板;若只是把一般選單設成 manual,使用者很容易找不到收起它的方法。
提示出現時不想關閉選單,檢查 hint 與 fallback
依 MDN 的 hint 說明,顯示 hint 不會把已開啟的 auto 浮層關掉;但這不代表點擊選單外部也不會關閉它,外部點擊仍可能觸發 light dismiss。若提示由 hover 開啟,還要支援鍵盤 focus,並在 mouseleave/blur 時明確隱藏。
支援一般 Popover API 不等於支援 hint。不支援 hint 的環境可能退成 manual,因此不能依賴點外部或 Esc 作為唯一退路。這個純顯示檢查可貼進目標瀏覽器 Console:
const probe = document.createElement('div');probe.setAttribute('popover', 'hint');console.log({ api: typeof probe.showPopover === 'function', hint: probe.popover === 'hint',});此檢查只確認 API 與屬性辨識,不能證明關閉、焦點和定位都正確。若 hint 不可用,簡單說明可直接放在頁面上;不要用 CSS 隱藏重要提示,再等待一個不存在的 hover 開啟機制。本文於 2026-10-04 查核文件,尚未在各瀏覽器版本執行這份互動驗收。
Dialog 要用 modal 開啟方式
所有 popover 都是非 modal,進入 top layer 或畫出 ::backdrop 也不會讓背景 inert。<dialog> 本身也不保證阻擋背景:show() 和 open 屬性是非 modal;需要 modal 時使用 showModal(),並保留清楚的關閉與取消流程。細節見 MDN dialog 文件。
原生按鈕與浮層的關聯不會自動提供完整 menu 鍵盤模型。若浮層中其實是一組一般連結,先保留連結語意;需要應用程式選單時,才連同方向鍵、焦點移動與 role 一起設計,不要只加 role="menu"。
需要 JavaScript 時,使用元素方法而不是 class 切換
程式控制可用 showPopover()、hidePopover() 與 togglePopover()。先確認元素真的支援這些方法,才能在舊環境提供退路:
const help = document.querySelector('#filter-help');
if (help && typeof help.showPopover === 'function') { help.showPopover();} else { // 這裡改顯示同一份說明的非浮層版本。}不要同時以 class 強制 display: block 來模擬開啟狀態;這會繞過 Popover API 的狀態與關閉規則。自訂外觀時可用 :popover-open,背景遮罩則用 ::backdrop:
#filter-help:popover-open { max-width: 22rem; padding: 1rem; border: 1px solid #cbd5e1; border-radius: 0.75rem;}上線前先測三件事
- 用鍵盤開啟按鈕,按 Esc 後焦點是否仍回到合理的位置。
- 確認浮層內沒有放必填、不可忽略的流程;那是 dialog 或正常頁面區塊的工作。
- 在你的支援瀏覽器與實機上測試。Popover API 已列為 Baseline 2025,但舊版瀏覽器不在這個保證範圍內。
若同時使用選單與提示,另驗收「選單保持開啟時 hover 提示」「Tab 到提示觸發點」「點擊外部」「Esc」四條路徑;針對 hint 與定位分別檢查相容性。浮層尺寸會隨內容改變時,也可參考 ResizeObserver 回饋迴圈排查,避免量測與改尺寸互相觸發。
原生 popover 的價值是減少簡單互動的狀態管理,而不是取代所有 overlay 元件。先把「讀者可否忽略它」判斷清楚,元件選擇就會自然明確。
參考資料: