承昨日「設計系統與設計代幣」——設計系統把靜態的一致性規模化了:一個 color.primary、一組間距刻度,讓一百個畫面看起來像同一個產品。但介面不是一張張靜止的截圖,它會被點、被滑、被切換。當使用者按下一顆按鈕、當清單新增一列、當頁面之間互相跳轉,中間那零點幾秒的「變化過程」也需要被設計。今天補上「動起來」這一層:微互動與動效設計,把昨天那套代幣思維延伸到時間軸上。

📖 學

微互動的四段結構

Dan Saffer 在《Microinteractions》裡把每一個微小的互動拆成四段,這是理解動效最好用的骨架:

  • 觸發(Trigger):啟動這次互動的來源。可以是使用者主動的(點按、滑動、拖曳),也可以是系統的(收到新訊息、倒數結束、網路斷線)。
  • 規則(Rules):互動發生時「會怎樣、不會怎樣」。例如按讚只能按一次、密碼欄位少於八碼就不讓送出。規則決定行為邏輯。
  • 回饋(Feedback):把規則翻譯成使用者看得懂的訊號。這正是動效最常出場的地方——按鈕被按下時凹陷、開關滑動、載入時的骨架屏。
  • 循環與模式(Loops & Modes):這次互動之後會怎樣、重複時會不會變。例如「稍後提醒」按第三次時文案會不會改口氣、訂閱到期後按鈕變成什麼狀態。

Nielsen Norman Group 給的定義更精煉:微互動是「觸發—回饋」的配對,回饋是針對觸發、範圍極窄、高度依情境的小型 UI 變化。換句話說,動效在這裡不是主角,是回饋這一段的表達手段。

動效不是裝飾,是有功能的

一個常見誤解是把動畫當成「炫技」或「越多越好」。NN/g 的立場很直接:動效最適合用在微互動的細微回饋上,而不是拿來取悅或娛樂使用者。真正有價值的動效,通常在做這四件事之一:

  • 狀態轉換:載入中 → 載入完成、關閉 → 開啟。讓使用者知道系統現在在哪個狀態。
  • 空間連續性:點一張卡片,它放大展開成詳情頁,而不是「啪」地跳到一個陌生畫面。動效維持了物件在空間中的來龍去脈,降低認知斷層。
  • 引導注意力:新增的項目輕輕淡入、錯誤欄位微微抖動,把眼睛帶到該看的地方。
  • 提供回饋:確認「你按到了、系統收到了」。少了這 0.1 秒的回應,介面會讓人懷疑到底有沒有反應。

判準很簡單:如果拿掉這個動畫,使用者會不會更難理解發生了什麼事?會,就留;不會,它多半只是雜訊。

緩動曲線與時長:讓動作像真的

現實世界沒有東西是「等速」啟動又「等速」煞停的,所以線性(linear)動畫看起來總是機械、廉價。緩動(easing)就是描述「速度隨時間怎麼變化」的曲線:

曲線感覺典型用途
ease-out(減速)快速進場、慢慢停下元素進入畫面、彈出視窗
ease-in(加速)慢慢啟動、加速離開元素離開畫面
ease-in-out(標準)兩頭慢、中間快畫面內的位移與變形
spring(彈簧)帶一點回彈與慣性拖曳放開、需要「活力感」的互動

Material Design 3 把緩動分成「Emphasized(強調)」與「Standard(標準)」兩套:多數轉場用強調集帶出自然感,追求速度與效率時才用標準集。時長也不是一個數字打天下——小變化用短時間、大位移用長時間,離開畫面的元素可以更快。

實務上有個好記的區間:多數 UI 微互動落在 100–300ms。低於 100ms 使用者幾乎感知不到過程,反而像瞬間跳變;超過 400ms 就開始覺得「拖」、覺得在等。按鈕回饋、開關切換這種小動作靠近 100–150ms;頁面級的大轉場才需要往 300ms 以上走。原則是:使用者會重複看到的轉場,寧短勿長。

把動效 token 化,納入設計系統

這裡就接回昨天的設計代幣了。既然顏色、間距可以是 token,動效當然也可以。把時長與曲線抽成語意化的變數:

motion.duration.short   = 150ms
motion.duration.medium  = 250ms
motion.easing.standard  = cubic-bezier(0.2, 0, 0, 1)
motion.easing.emphasized = cubic-bezier(0.2, 0, 0, 1)

好處和顏色 token 一模一樣:整個產品的動效節奏一致,不會這顆按鈕 200ms、那顆 500ms;要調整節奏時改一處就全站生效;設計與工程用同一套詞彙溝通。動效從「每個工程師憑手感填數字」變成系統的一部分。

無障礙:prefers-reduced-motion

動效不是對每個人都友善。位移、縮放、視差這類大範圍運動,可能誘發前庭失調(vestibular disorder)使用者的暈眩與不適。呼應前幾天談的 a11y,CSS 提供了 prefers-reduced-motion 媒體查詢,偵測使用者是否在系統層開了「減少動態效果」:

@media (prefers-reduced-motion: reduce) {
  * { animation: none; transition: none; }
}

MDN 特別提醒:這不代表要移除「所有」動畫。若某個動態是傳達資訊或功能所必需的,仍可保留;該關掉的是那些非必要、純為裝飾的運動。更細緻的做法是把大位移換成單純的淡入淡出,既尊重偏好又不丟失狀態提示。把這條媒體查詢寫進設計系統的動效 token 層,就能讓「尊重減少動態」變成預設,而不是每個元件各自補救。

🧠 記

  • 微互動四段:觸發 Trigger → 規則 Rules → 回饋 Feedback → 循環與模式 Loops/Modes(Dan Saffer 模型),動效主要活在「回饋」這段。
  • 動效有四種功能性目的:狀態轉換、空間連續性、引導注意力、提供回饋;拿掉會不會更難懂,是留與不留的判準。
  • 緩動不用線性:ease-out 進場、ease-in 離場、ease-in-out 內部位移、spring 帶彈性;現實世界沒有等速的運動。
  • 時長多落在 100–300ms:小動作靠近 100–150ms,大轉場往 300ms,重複看到的寧短勿長。
  • 動效可以 token 化納入設計系統;並用 prefers-reduced-motion 尊重前庭失調使用者,該關的是裝飾性運動而非全部。

✍️ 實踐

今天花 20–30 分鐘,挑你正在做或常用的一個介面,做一次「動效體檢」:

  1. 選一個微互動(例如一顆送出按鈕、一個展開/收合面板),用四段結構把它拆開:觸發是什麼?規則有哪些?回饋現在怎麼表達?有沒有循環或模式變化?
  2. 對它現在的動畫問一句:這個動效在做四種目的的哪一種?如果四種都不沾邊,它可能只是裝飾——考慮拿掉或簡化。
  3. 打開開發者工具,量一下(或估一下)它的 transition-duration 與 easing。若是 linear 或超過 400ms,改成 ease-out、拉回 150–250ms,親自感受差別。
  4. 在 CSS 加上一段 @media (prefers-reduced-motion: reduce),把大位移降級成淡入淡出,然後到系統設定開啟「減少動態」驗證它真的生效。

做完你會發現:好的動效常常是「你沒注意到,但拿掉就怪」的那種。

🔗 延伸學習

💬 問 AI

把你的元件動畫貼給 AI,請它從「功能性」而非「好不好看」的角度審視:

我在設計一個 [元件名稱,例如:通知橫幅 / 下拉選單] 的動效,現況如下:
- 觸發:[使用者做了什麼 / 系統發生什麼]
- 目前動畫:[時長、easing、位移或縮放方式]

請幫我:
1. 用 Dan Saffer 的四段結構(觸發/規則/回饋/循環)拆解這個微互動,指出我漏掉哪一段。
2. 判斷這個動效對應哪一種功能性目的(狀態轉換/空間連續性/引導注意力/提供回饋);若四種都不沾邊,直說它是裝飾。
3. 針對時長與 easing 給具體建議(數字 + cubic-bezier),並說明為什麼。
4. 給我一段 prefers-reduced-motion 的降級寫法,保留必要的狀態提示。