題目與情境
模態框是目前活動介面,背景仍可見但不可用。實作要保留觸發按鈕,支援 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,應使用合適的展開語意。
觸發按鈕消失怎麼辦?
把焦點恢復到最近的合理控制項,例如更新後的列或頁面標題,並在需要時播報結果。不要聚焦已脫離或停用的元素。