核心觀念

按鈕的每種視覺狀態都傳達一種系統訊息,缺少任何一種,使用者就失去對應的判斷依據。三層回饋模型回答「什麼時候給回饋」,本篇回答「用什麼視覺狀態給回饋」— 從無互動、游標懸停、鍵盤焦點到處理中,一顆按鈕的生命週期裡每個階段都有它要對使用者說的話。

基本狀態

狀態觸發條件傳達訊息必要性
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 + 結果通知]
23                                      └─失敗→ [Default + 錯誤訊息]

要點

  1. Active → Loading 的過渡 在使用者釋放點擊後立即發生(不等伺服器回應)
  2. Loading 期間按鈕 disabled — 這是設計需求不是實作細節
  3. Loading → Default 必須發生 — 不論成功失敗,按鈕必須恢復可操作狀態
  4. 結果通知獨立於按鈕 — 成功/失敗訊息用 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: Statesm3.material.io/foundations/interaction/states)— Google 設計系統的互動狀態定義
  • WCAG 2.1 Success Criterion 2.4.7: Focus Visible — 焦點狀態可見性的無障礙標準
  • Apple Human Interface Guidelines: Buttons — Apple 的按鈕設計原則