開發紀錄
手機導覽的開合與焦點:先分清 disclosure 和 modal
從原生 details 手機導覽,說明展開連結、Escape、外部點擊與焦點還原的責任,避免把一般導覽誤當成需要鎖住整頁的 modal。
- HTML
- 導覽設計
- 鍵盤操作
- 漸進增強
手機選單展開後,畫面上多了一塊浮動面板,卻不一定表示讀者必須先關掉它,才能繼續操作頁面。這個差別會影響 Tab 該去哪裡、Escape 做什麼,以及選單關掉後,焦點要留在哪裡。
本站目前的手機導覽採用 disclosure,也就是由一個入口展開或收合一組連結。它不是 modal,沒有把其餘文件設成不可操作。2026 年 10 月 26 日,我沿著實際 HTML 和事件處理,分開檢查了這些責任。
只是展開導覽,不需要先接管整個頁面
選單裡的項目是前往筆記、產品、作品、合作與關於頁的連結。讀者要做的是選一個目的地,不是完成一段必須暫停其他操作的流程。
W3C 的 disclosure navigation 範例也特別區分:日常說的「選單」,不等於需要宣告 WAI-ARIA 的 menu 角色;一般網站導覽通常不需要那套複合元件的完整鍵盤行為。[1]
本站因此保留原生連結和一般 Tab 順序,沒有加上 menu、menuitem,也沒有把焦點圈在面板裡。這不表示 modal 不好,而是兩種互動的責任不同。若改成需要讀者先完成或取消的對話流程,才該重新評估背景能否操作與焦點限制。
原生入口先負責開合
手機導覽的外層是 details,入口是第一個 summary。HTML 本身就把這組元素定義為揭露控制;summary 是內容的標示,不必在裡面再放一顆負責同一件事的 button。[2]
共用 Button 元件在這裡只提供外觀,實際輸出仍是 summary。面板內的目的地也已存在於初始 HTML,不需要開啟之後再由腳本建立。
這讓沒有 JavaScript 的情況仍有基本入口。我禁止頁面腳本後重新載入關於頁,讓手機導覽的 summary 取得焦點,再送出 Enter 和 Space:前者打開導覽,後者把它收合。少掉的是客製的關閉效果和額外事件,不是整組連結。
原生開合不會順便提供所有關閉方式。外部點擊和本站設定的 Escape 行為,都要另外看腳本,不能因為 details 會開,就把它們算成同一份保證。
Escape 的工作不只讓面板消失
有腳本時,我在開啟的導覽按 Tab,焦點進入第一個筆記連結;接著按 Escape,面板收合,焦點回到控制它的 summary。
這個還原有實際用途。如果只是把面板藏起來,卻不處理原本位於內部連結的焦點,讀者可能不知道下一次鍵盤操作會從哪裡開始。本站的 Escape 處理明確呼叫入口的 focus(),不是期待動畫結束後瀏覽器自行猜測。
外部點擊走的卻是另一條路:它會收合手機導覽,沒有再強制把焦點拉回入口。讀者既然已經點向面板外,就不應把 Escape 的焦點策略不加區分地套到所有關閉原因。
目前也沒有「Tab 一離開導覽就自動關閉」的處理。W3C 範例包含這種安排,但本站不是那份範例的逐項實作。[1] 有參考模式,不代表可以直接宣稱具備其中所有互動。
收合動畫只是增強層
一般模式下,腳本在關閉時加入 is-closing,讓面板先淡出並稍微位移,再把 details 的開啟狀態移除。程式設定了 200 毫秒的收尾 timer;這是設定值,不是量到的操作延遲。
啟用 reduced-motion 時,收合分支直接關閉,CSS 也移除開啟動畫。我用瀏覽器模擬這項偏好後操作,確認面板能關閉,沒有留下收合中的 class。
可以把幾條路徑分開記錄:
| 操作情境 | 基本責任 | 本站額外處理 |
|---|---|---|
| 開啟 summary | 展開原生 disclosure | 顯示面板的進場效果 |
| 在導覽內按 Escape | 腳本處理關閉 | 焦點回到 summary |
| 點擊導覽以外 | 腳本處理關閉 | 不額外強制還原焦點 |
| 停用頁面腳本 | 保留原生開合和連結 | 不提供上述客製事件與轉場 |
離頁時還會清掉關閉 timer 和暫時 class。這是資源收尾的程式安排,不是已完成所有歷史返回情境的證據。
先驗證一條完整操作路徑
檢查手機導覽時,我會先走完「找到入口、打開、進入連結、關閉、確認焦點」這條路,而不是只看圖示會不會改變。再把外部點擊、降低動態效果與停用腳本分開測,才能知道每一層提供什麼。
這次的本機 Edge 觀察使用 390 CSS px 的窄視窗,包含真實鍵盤與滑鼠輸入;不是實體手機、螢幕閱讀器或跨瀏覽器驗收。介面是否好讀、面板大小是否合適,仍要另外看實際閱讀情境。
原生 details 的單開、鍵盤與無腳本退路談的是經歷內容如何展開;手機導覽多了一個目的地與焦點問題。選對原生入口之後,還是要把每一種關閉原因說清楚。
Sources
[1] https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation — W3C APG: Example Disclosure Navigation Menu [2] https://html.spec.whatwg.org/multipage/interactive-elements.html — WHATWG HTML: Interactive elements