具代表性的面試主題

前端面試:如何用 inert 實作可存取的模態框?

前端中等
Offer.cc 編輯團隊發佈 更新

題幹

儀表板上方開啟一個模態編輯器。如何阻止鍵盤、指標和輔助技術使用者操作背後頁面,同時保證焦點恢復?

題目與情境

模態框是目前活動介面,背景仍可見但不可用。實作要保留觸發按鈕,支援 Escape 和關閉控制,避免依賴複雜的正 tabindex。

面試官考察什麼

  • 理解 inert 阻止什麼,以及它不會自動配置什麼。
  • 結合原生對話框語意、焦點管理和可存取名稱。
  • 處理 Portal、動畫時序、瀏覽器支援和減少動效。

作答前的釐清問題

  • 這是模態對話框,還是允許操作背景的非模態浮層?
  • 對話框歸屬哪個元素,Portal 掛載在哪裡?
  • 開啟、取消、提交和關閉時焦點應該去哪裡?
  • 是否需要支援舊瀏覽器?

30 秒回答框架

支援時我會使用原生模態對話框,把焦點移到有名稱的標題或首個有效控制項,並在開啟期間只給對話框外的應用程式外殼設定 inert。關閉後把焦點恢復到仍存在的觸發按鈕,提供 Escape 和明確關閉按鈕,並測試鍵盤與讀屏路徑。inert 負責阻止背景互動,不取代命名、焦點恢復或狀態管理。

分步深入

1. 選擇正確語意表面

瀏覽器基線允許時,真正的模態使用原生 dialog 元素和 showModal(),透過可見標題或 aria-labelledby 提供名稱。非模態展開不應讓整頁 inert,因為使用者預期能在介面之間移動。

2. 隔離背景

inert 設定到對話框外的應用程式容器,不要設定到同時包含 Portal 對話框的共同祖先。瀏覽器會讓 inert 子樹離開焦點導覽並阻止焦點事件,也阻止正常使用者互動。不要在包含目前焦點對話框的祖先上散落 aria-hidden

3. 管理焦點生命週期

開啟前保存觸發按鈕。開啟後將焦點放到穩定標題或首個任務控制項,而不是任意關閉圖示。取消或提交成功後關閉、移除 inert;若觸發按鈕仍可見且啟用則恢復焦點,否則選擇附近合理目標並在需要時播報結果。

4. 處理 Portal 與過渡

將對話框渲染到頂層,避免裁剪和層疊上下文限制。互動前先設定 inert,掛載後再設定焦點。根據減少動效偏好協調進出動畫,任何中斷路徑都不能留下背景鎖定。

5. 測試失敗路徑

測試 Tab、Shift+Tab、Escape、關閉按鈕、驗證錯誤、巢狀對話框、路由變化和讀屏播報。確認點擊、程式化焦點、頁內尋找和指標事件符合瀏覽器的 inert 行為。只有相容範圍需要時才加入回退實作。

高品質示範回答

「真正的模態我會使用原生對話框,把焦點放到有名稱的標題或首個任務控制項,並把 inert 設定在應用程式外殼上,確保 Portal 對話框不在 inert 子樹內。開啟前保存觸發按鈕,關閉後恢復焦點,支援 Escape 和明確關閉按鈕。焦點、命名和驗證獨立於 inert;還要測試鍵盤、讀屏、Portal、動畫和路由變化,並在中斷時清理 inert。」

常見誤區

  • 把 inert 設定到包含 Portal 的應用程式根 → 對話框也會 inert → 把對話框掛在 inert 子樹之外。
  • 把 inert 當作焦點管理器 → 開啟或關閉時焦點仍可能錯誤 → 定義完整焦點生命週期。
  • 背景含焦點時使用 aria-hidden → 輔助技術狀態不一致 → 先移動焦點,再讓背景 inert。
  • 忘記中斷動畫 → 頁面會一直被鎖定 → 在每條關閉和卸載路徑清除 inert。

追問與回答

inert 會取代焦點陷阱嗎?

它讓背景不可聚焦,因此模態通常不必手寫焦點陷阱。但仍要設定初始焦點、恢復焦點、命名對話框,並準備瀏覽器或元件回退。

非模態抽屜能用 inert 嗎?

只有產品明確要求背景不可用時才用。允許同時操作背景的抽屜不應讓頁面 inert,應使用合適的展開語意。

觸發按鈕消失怎麼辦?

把焦點恢復到最近的合理控制項,例如更新後的列或頁面標題,並在需要時播報結果。不要聚焦已脫離或停用的元素。

公開來源

同類題目