工具提示感覺就像是你能遇到的最小的 UI 問題。它們很小而且通常是隱藏的。當有人問如何建立一個時,傳統的答案幾乎總是使用一些 JavaScript 函式庫。很長一段時間以來,這都是明智的建議。 我也跟著做了。 從表面上看,工具提示很簡單。將滑鼠懸停或聚焦在某個元素上,顯示一個帶有一些文字的小框,然後在使用者離開時將其隱藏。但一旦你將其交付給真正的用戶,優勢就開始顯現出來。鍵盤使用者按 Tab 鍵進入觸發器,但永遠看不到工具提示。螢幕閱讀器會宣布兩次,或者根本不宣布。當您移動滑鼠太快時,工具提示會閃爍。它與較小螢幕上的內容重疊。按 Esc 不會將其關閉。焦點失去了。 隨著時間的推移,我的工具提示程式碼變成了我不想再擁有的東西。事件偵聽器堆積起來。懸停和焦點必須分開處理。外部點擊需要特殊情況。 ARIA 屬性必須手動保持同步。每個小修正都增加了另一層邏輯。 圖書館有所幫助,但它們也更像是我工作的黑盒子,而不是完全了解幕後發生的事情。 這就是促使我研究更新的 Popover API 的原因。我想看看如果我在沒有程式庫的幫助下使用瀏覽器的本機模型重建單一工具提示會發生什麼。 在我們開始時,值得注意的是,與任何新功能一樣,有一些問題仍在解決中。也就是說,儘管整個 API 有幾個部分在不斷變化,但它目前享有良好的瀏覽器支援。同時,值得關注 Caniuse。 「舊」工具提示 在 Popover API 出現之前,使用工具提示庫並不是捷徑。這是預設的。瀏覽器沒有跨滑鼠、鍵盤和輔助技術運行的工具提示的原生概念。如果您關心正確性,那麼您唯一的選擇就是使用庫,而這正是我所做的。 在較高的層次上,模式總是相同的:一個觸發器元素、一個隱藏的工具提示元素以及協調兩者的 JavaScript。
<按鈕類別=“訊息”>? 按鈕>
該庫處理了允許元素在懸停或聚焦時顯示、在模糊或滑鼠離開時隱藏以及在滾動時重新定位/調整大小的連接。
隨著時間的推移,工具提示可能會變得脆弱。微小的改變也會帶來風險。小修復導致回歸。更糟的是,添加新的工具提示繼承了相同的複雜性。從技術上來說事情是可行的,但從來沒有感覺已經解決或完成。 這就是我決定使用瀏覽器的原生 Popover API 重建工具提示時的情況。 我嘗試 Popover API 的那一刻 我沒有改用 Popover API,因為我想嘗試一些新東西。我切換是因為我厭倦了維護工具提示行為,我相信瀏覽器應該已經理解了。 一開始我很懷疑。大多數新的 Web API 都承諾簡單性,但仍然需要黏合、邊緣情況處理或回退邏輯,以悄悄地重新創建您試圖逃避的相同複雜性。 因此,我以盡可能最小的方式嘗試了 Popover API。看起來是這樣的:
<按鈕popovertarget =“tip-1”>? 按鈕>
1.鍵盤“正常工作” 鍵盤支援取決於正確排列的多個層:焦點必須觸發工具提示,模糊必須隱藏它,Esc 必須手動連接,並且時機很重要。如果您錯過了一種邊緣情況,工具提示要么保持打開狀態太長時間,要么在閱讀之前消失。 將 popover 屬性設為自動或手動時,瀏覽器將接管基礎功能:Tab 和 Shift+Tab 正常運行,Esc 每次都會關閉工具提示,並且不需要額外的偵聽器。
從我的程式碼庫中消失的是全域按鍵處理程序、特定於 Esc 的清理邏輯以及鍵盤導航期間的狀態檢查。鍵盤體驗不再是我必須維護的東西,它變成了瀏覽器的保證。 2. 螢幕閱讀器的可預測性 這是最大的進步。正如我之前概述的那樣,即使 ARIA 工作很仔細,行為也會有所不同。每一個微小的改變都讓人覺得有風險。使用具有適當角色的彈出視窗看起來和感覺更加穩定和可預測,就將發生的事情而言:
這是另一個勝利:切換後,Lighthouse 不再標記互動的錯誤 ARIA 狀態警告,這主要是因為不再有自訂 ARIA 狀態讓我意外出錯。
3. 焦點管理 焦點曾經是脆弱的。之前,我有這樣的規則:讓焦點觸發器顯示工具提示,將焦點移到工具提示中並且不關閉,當觸發器太近時模糊觸發器,以及關閉工具提示並手動恢復焦點。這一直有效,直到沒有效果。 透過 Popover API,瀏覽器強制執行更簡單的模型,其中焦點可以更自然地轉移到彈出視窗中。關閉彈出視窗會將焦點返回觸發器,並且不會出現看不見的焦點陷阱或失去焦點的時刻。而且我沒有添加焦點恢復程式碼;我把它去掉了。
結論 Popover API 意味著工具提示不再是您模擬的東西。它們是瀏覽器可以理解的東西。開啟、關閉、鍵盤行為、轉義處理和大部分可訪問性現在都來自平臺本身,而不是來自臨時 JavaScript。 這並不意味著工具提示庫已經過時,因為它們對於複雜的設計系統、大量定製或遺留約束仍然有意義,但預設值已經發生了變化。第一次,最簡單的工具提示也可能是最正確的。如果您好奇,請嘗試這個實驗:只需用 Popover API 替換產品中的一個工具提示,不要重寫所有內容,不要遷移整個系統,只需選擇一個,看看程式碼中會消失什麼。 當平台為您提供更好的原語時,您的勝利不僅是減少了 JavaScript 行數,而且還減少了您需要擔心的事情。 查看我的 GitHub 儲存庫中的完整原始程式碼。 進一步閱讀 若想更深入了解彈出視窗和相關 API:
傑夫·格雷厄姆《Poppin' In》 “澄清彈出視窗和對話框之間的關係”,Zell Liew “什麼是popover=提示?”,Una Kravets “呼叫者命令”,丹尼爾·施瓦茨 “使用 HTML 彈出視窗建立自動關閉通知”,Preethi 開啟 UI Popover API 解釋器 “彈出氣球”,約翰·雷亞 “CSS 錨點定位”,胡安·迭戈·羅德里格斯
MDN 也提供了 Popover API 的全面技術文件。