開發紀錄
原生 details 的單開、鍵盤與無腳本退路
從關於頁的經歷卡片,拆開 details、summary、單開群組和動畫腳本的責任,確認沒有 JavaScript 時,內容仍能由鍵盤展開。
- HTML
- 漸進增強
- 鍵盤操作
- 互動驗證
一排經歷卡片收合之後,頁面確實比較短。但讀者還需要知道每一筆是什麼、怎麼打開,以及開了下一筆之後,上一筆會不會消失。這些都要先有決定,才輪到展開動畫。
本站關於頁使用原生 details 與 summary,再以少量腳本補上動畫和捲動。2026 年 10 月 25 日,我把有腳本、停用頁面腳本,以及模擬 reduced-motion 的操作分開核對。想確認的是:拿掉動畫層之後,閱讀入口還在不在。
summary 要說清楚展開的是什麼
details 適合承載可以展開查看的補充資訊;第一個 summary 子元素則提供這段內容的摘要或標示。這是 HTML 本身的揭露控制,不需要先把一個 div 改寫成自製按鈕。[1]
目前經歷卡片的 summary 包含時間、公司與職稱。收合後,讀者仍能辨識這筆經歷,不必先打開才知道裡面是什麼。右側箭頭只表達開合狀態,設為 aria-hidden,不讓裝飾圖示成為另一份控制名稱。
有視覺作品可看的項目,另外提供一個作品連結。這個連結在 DOM 裡是 details 的外部同層元素,不是藏在 summary 內。展開經歷與開啟作品是兩個目的,視覺上可以靠近,操作責任仍然分開。
這個區別也適用於其他卡片:如果標題要展開內容,旁邊的圖示卻要導向另一頁,就不要只因為它們畫在同一條橫列,就把兩個動作塞進同一個控制裡。
單開是閱讀取捨,不是 accordion 的必要答案
這組經歷的 details 共用 name="career"。HTML 的同名群組會維持最多一筆展開;開啟另一筆時,瀏覽器會關閉原本那筆。不必自己遍歷其他卡片,再逐一移除 open。[1]
「最多一筆」也包括全部收合。本站初始 HTML 只預設開啟其中一筆,讀者仍可以把它關起來,不需要強制留下某個選取項目。
這種安排適合逐筆閱讀,卻不適合所有內容。HTML 規格也提醒,互斥展開可能妨礙需要同時比較多筆資訊的人。[1] 如果是要對照方案、規格或不同時間的差異,我會重新評估是否允許多筆一起開,不會把單開當成原生元件附贈、因此一定要採用的功能。
還有一個容易寫錯的地方:open 是布林屬性,看的是屬性是否存在,不是字串看起來像 true 或 false。要輸出收合狀態,應該省略它,而不是留下 open="false"。[1]
先保住鍵盤入口,再談動畫
本機操作時,我先讓第二筆 summary 取得焦點,再送出 Enter。它開啟,原本那筆收合;對已開啟的 summary 按 Space,則回到全部收合。滑鼠點另一筆,也只留下被點選的那筆。
這些操作走的是瀏覽器輸入事件,不是直接在程式裡把 open 設成 true。直接改狀態可以檢查版型,卻不能替讀者證明鍵盤真的進得去。
目前 summary 沒有再包一層 button,也沒有另外建立方向鍵切換項目的控制。它提供的是原生展開/收合,不應因為畫面長得像 accordion,就宣稱還有另一套複合元件的鍵盤行為。
頁面保留共用的 focus-visible 樣式。不過,焦點樣式存在和輔助科技操作完整是兩件事:這次的 Enter、Space 與滑鼠觀察,沒有涵蓋螢幕閱讀器、所有焦點順序或跨瀏覽器驗收。
腳本增加的是轉場與視窗位置
關於頁腳本沒有接管所有開合狀態。對一筆已展開的卡片進行一般收合時,它會先攔下預設動作,加入 is-closing,讓內容淡出並稍微位移,再結束收合。程式也準備了 200 毫秒的 timer 作為收尾路徑;這是實作中的設定,不是量到的操作延遲。
開啟另一筆之後,腳本會安排捲動,讓該筆靠近導覽列下方。這是視窗位置的調整,不是把鍵盤焦點移進內文,也不是單開規則的來源。
因此,判斷這個互動時,我會分開看兩件事:details 是否真的開啟,以及畫面是否完成轉場。不能因為某一瞬間還在淡出,就立刻把它當成開合狀態失效;也不能只看到淡出,就忽略最後是否真的移除了 open。
當 reduced-motion 生效時,收合分支保留原生動作,CSS 也移除這組內容的開啟動畫。模擬這個媒體條件後,我確認卡片可以關閉,沒有留下 is-closing。這是瀏覽器內的媒體模擬,不是所有作業系統設定或裝置都已測過。
沒有 JavaScript,仍然能讀到展開內容
我另外禁止頁面腳本執行後重新載入關於頁,再用 Enter 與 Space 開啟不同項目。同名群組仍然只保留一筆展開,內容也仍是頁面原本的 HTML。
這個退路成立,是因為 summary 和經歷正文從一開始就存在,而不是點下去之後才由腳本產生。無腳本時少掉的是客製的收合轉場與開啟後捲動,不是讀者取得內容的入口。
| 情境 | 這次確認的行為 |
|---|---|
| 一般模式按 Enter | 指定項目開啟,前一項收合 |
| 一般模式按 Space | 已開項目關閉,可以全部收合 |
| 滑鼠點 summary | 對應項目開啟,維持單開 |
| 停用頁面腳本 | Enter、Space 與原生單開仍成立 |
| 模擬 reduced-motion | 可正常收合,沒有殘留收合中的 class |
這是一次本機 Edge 的功能觀察,不包含歷史返回快取、輔助科技或主觀手機閱讀驗收。原生標籤提供可用的起點,不會替作者完成所有內容、焦點與閱讀設計。
看起來像按鈕,不代表它真的該是 <button>談的是相同的選擇:先讓 HTML 表達操作的目的。這組卡片要揭露的是補充經歷,所以先由 details 承擔開合,再決定哪些動畫值得加上去。
Sources
[1] https://html.spec.whatwg.org/multipage/interactive-elements.html