按鈕狀態設計:一個按鈕的完整生命週期
核心觀念
按鈕的每種視覺狀態都傳達一種系統訊息,缺少任何一種,使用者就失去對應的判斷依據。三層回饋模型回答「什麼時候給回饋」,本篇回答「用什麼視覺狀態給回饋」— 從無互動、游標懸停、鍵盤焦點到處理中,一顆按鈕的生命週期裡每個階段都有它要對使用者說的話。
基本狀態
| 狀態 | 觸發條件 | 傳達訊息 | 必要性 |
|---|---|---|---|
| Default | 無互動 | 「可以按我」 | 必要 |
| Hover | 游標懸停(桌面端) | 「這是可互動的元件」 | 桌面端必要 |
| Active / Pressed | 點擊中(手指按住) | 「系統收到點擊了」 | 必要 |
| Focus | 鍵盤 Tab 導航選中 | 「目前焦點在這裡」 | 無障礙必要 |
| Disabled | 前置條件未滿足 | 「現在不能按」 | 必要 |
| Loading | 非同步操作處理中 | 「正在處理,請等待」 | 非同步按鈕必要 |
前五種狀態出自 NN/g 與 Material Design 的互動狀態定義;Loading 則來自非同步按鈕的回饋需求(等待指示 + 防重複提交)— 本篇把它跟五個通用狀態並列,因為缺了它、非同步按鈕的生命週期就不完整。切換型控件(toggle、segmented control)另有 selected 態 —「現在是開還是關」也是一種系統訊息;本表聚焦動作按鈕,選取態屬選擇控件設計。
Default
按鈕的初始狀態(三層回饋模型的狀態流程圖以 idle 標記的就是這個狀態)。設計重點:讓使用者一眼辨識「這是個按鈕」。常見設計手法包括填色背景、邊框、圓角矩形、陰影。與普通文字或裝飾元素的區別必須明確。
Hover(桌面端)
游標移到按鈕上方時的狀態。行動裝置沒有 hover 概念(手指碰到螢幕就是點擊),這個狀態僅對桌面端(含 web)有意義。常見做法是背景色稍微加深或加上微陰影。
Active / Pressed
使用者按住按鈕瞬間的狀態。對應三層回饋模型的第一層「點擊確認」。視覺上通常表現為凹陷效果、顏色加深或縮小動畫。在觸控裝置上可搭配觸覺回饋(震動)。
Focus
透過鍵盤 Tab 鍵導航到按鈕時的狀態。這是無障礙設計(Accessibility)的基本要求 — WCAG 2.1 要求所有可互動元素在獲得焦點時必須有可見的視覺指示。常見做法是加上明顯的邊框或外框光暈。
Disabled
按鈕不可操作時的狀態。設計要點:
- 視覺上與可操作狀態有明確區別(通常降低透明度)
- 告知使用者「為什麼不能按」 — 單純灰掉不夠。優先用常駐說明文字(按鈕旁的條件提示);tooltip 只在桌面端可行 — 行動端沒有 hover、disabled 元素通常也不接收 focus,hover 觸發的提示對行動端與鍵盤使用者不可達
- disabled 與隱藏的分工:條件可由使用者滿足時用 disabled(灰掉 + 說明怎麼解鎖,讓使用者知道功能存在);條件與使用者無關(權限不足、功能未開通且無法自行開通)時考慮隱藏 — 展示一個永遠按不了的按鈕只製造困惑
Loading
非同步操作處理中的狀態。對應三層回饋模型的第二層「等待指示」。設計要點:
- 按鈕內容替換為 spinner 或文字變更(「送出」→「送出中…」)
- 按鈕自動進入 disabled(防重複提交)
- 操作完成後必須恢復到 default 或顯示結果
- 設定逾時:取值略大於 client / 後端 timeout,逾時後恢復並給錯誤訊息(兜底原則同三層回饋模型畫面級的 timeout 段)
非同步按鈕的狀態流
非同步按鈕=點擊後需要等待伺服器或 IO 回應的按鈕(送出表單、呼叫 API);同步按鈕=操作在本地立即完成的按鈕(導航、切換)。
1[Default] ─點擊→ [Active] ─釋放→ [Loading] ─完成→ [Default + 結果通知]
2 │
3 └─失敗→ [Default + 錯誤訊息]要點
- Active → Loading 的過渡 在使用者釋放點擊後立即發生(不等伺服器回應)
- Loading 期間按鈕 disabled — 這是設計需求不是實作細節
- Loading → Default 必須發生 — 不論成功失敗,按鈕必須恢復可操作狀態
- 結果通知獨立於按鈕 — 成功/失敗訊息用 SnackBar 或畫面更新呈現(形式選擇見通知模式選擇),不塞在按鈕裡
同步按鈕的狀態流
1[Default] ─點擊→ [Active] ─釋放→ [Default](操作在釋放時同步完成)同步按鈕不需要 Loading 狀態。防連點用 debounce 處理,不用 disabled — disabled 會讓按鈕在每次點擊後閃跳灰態,而第一次點擊本來就該立即生效;「立即執行、短時間內忽略後續點擊」的執行語意,三層回饋模型的防連點段有完整說明。
落點:設計系統元件層
這些狀態的實作落點在共用 Button 元件層,不是逐顆按鈕。Material、Cupertino 等平台元件庫已內建 hover / pressed / focus 的視覺處理,真正要補的通常只有 Loading 與 Disabled 的語意 — 何時進入、何時恢復、disabled 原因怎麼給。估工時以「元件層一次工 + 各按鈕接上狀態來源」計算,而非「按鈕數 × 狀態數」— 後者會把成本高估數倍,讓完整的狀態設計看起來做不起。
元件語意與版面
狀態清單之外,按鈕的文字、圖示、選中視覺與所在的版面各自承載語意,常見缺口:
切換元件的標籤要能區分「現態」與「動作」。「顯示目標模式」(播放鍵顯示「播放」)和「顯示當前模式」(開關顯示現態)是兩種並存慣例,單顆文字按鈕無法自證是哪種 — 名詞標籤(「管理模式」)特別容易被讀成狀態指示。消歧做法:狀態顯示與動作按鈕分離(非互動的現態文字 +「切換模式」動作鈕)、或改用自帶 on/off 語意的控件(switch / segmented control)。不幫助消歧的圖示是雜訊、應移除(U.C15)。
非互動指示不可與動作按鈕同形。狀態圖示混排在動作按鈕同列、又用近似圖形(描邊 vs 實心)時,使用者的預設是整列可點 — 點到指示的「沒反應」被讀成按鈕壞掉。描邊 / 實心差異不是可靠的互動性訊號;指示要用明顯非按鈕的形態(文字 chip、圓點)或移出動作列,同一個圖形全畫面只承載一個語意(U.C18)。
選中態是(底色, 文字色)的成對設計。只設定選中底色、文字色走主題預設,組合對比沒有人驗證過 — 淺藍選中底疊淺色預設文字就是「選中後看不到字」的成因。對比方向成對反轉:底色淺配深字、底色深配淺字,逐狀態驗 WCAG AA(一般字級 4.5:1、大字 3:1)(U.C17)。
水平排列的元件列溢出時要有捲動 affordance。chip 列、按鈕列超出畫面寬度時,截斷的預設讀法是「壞了」或「被旁邊的元件遮住」、不是「可以捲」— 提示手段:邊緣漸層遮罩、下一個項目部分露出、方向箭頭、捲軸指示;選項少時優先消除溢出(wrap 換行、改選單)。截斷邊緣緊貼固定按鈕會讓視覺歸因錯到那顆按鈕上 — 一條實作正確的可捲動篩選列因此在驗收被回報成「被重新整理按鈕遮蔽」(U.C16)。
常見設計失誤
| 失誤 | 後果 | 修正 |
|---|---|---|
| Loading 狀態未禁用按鈕 | 重複提交 | Loading 自動帶入 disabled |
| Disabled 沒有說明原因 | 使用者困惑「為什麼不能按」 | 搭配 tooltip 或條件說明 |
| Focus 狀態不可見 | 鍵盤使用者無法導航 | 加明顯 focus ring |
| Active 狀態與 Default 視覺差異太小 | 觸控裝置上看不出「有按到」 | 加大視覺差異或加觸覺回饋 |
| 按鈕長期 Loading 無超時機制 | 介面永久凍結 | 設定逾時,逾時後恢復 + 錯誤訊息 |
設計檢查清單
逐一確認每個按鈕:
- 有 Default 狀態且明確可辨識為按鈕?
- 桌面端有 Hover 狀態?
- 有 Active / Pressed 視覺回饋?
- 有可見的 Focus 狀態(鍵盤導航)?
- Disabled 狀態有說明原因?
- 非同步按鈕有 Loading 狀態?
- Loading 期間按鈕 disabled?
- Loading 有超時機制(不會永久卡住)?
- Loading 結束後恢復可操作狀態?
- 切換型按鈕的文字讀起來是動作而非現態(或已拆成狀態顯示 + 動作按鈕)?
- 同列的非互動指示與動作按鈕形態可區分、圖示無撞名?
- Selected 態的底色與文字色成對設計、對比達 WCAG AA?
參考來源
- Nielsen Norman Group: “Button States: Communicate Interaction” — 按鈕各狀態如何傳達互動性的使用性研究
- Material Design 3: States(m3.material.io/foundations/interaction/states)— Google 設計系統的互動狀態定義
- WCAG 2.1 Success Criterion 2.4.7: Focus Visible — 焦點狀態可見性的無障礙標準
- Apple Human Interface Guidelines: Buttons — Apple 的按鈕設計原則
#ux-design #interaction-feedback #button-states #accessibility