動態語法:動畫何時才配得上它佔用的影格
多數介面動畫只是別著功能徽章的裝飾。我用的測試很直白:如果說不出一段動畫在告訴使用者什麼,它就配不上自己佔用的影格——刪掉。撐得過這個測試的東西,最後會收斂成一套很小的語法:四檔時長、兩條緩動規則,以及少數幾件動態確實比靜態變化做得更好的工作。其餘的一切,都不過是設計師以每次16毫秒的代價,拿使用者的時間取悅自己。 {.answer-block}
TL;DR
- 動態不是資訊,就是雜訊。 正當的工作只有四件:交代某個東西從哪裡來、又去了哪裡;確認操作已被接收;在變化發生時引導注意力;以及掩蓋無法避免的延遲。其餘一律砍掉。
- 四檔時長就涵蓋了整個介面: 按下與切換約100ms,游標停留與淡入淡出150-200ms,展開/收合250-300ms,頁面轉場與模態視窗300-400ms。
- 兩條緩動規則就涵蓋了進場與退場: 進入的元素用 ease-out,離開的元素用 ease-in。留在畫面上移動的元素用 ease-in-out;linear 留給進度條與純粹的淡入淡出。
- 刪除測試的位階高於品味測試。 「感覺不錯」會讓糟糕的動畫活下來,「它到底告訴使用者什麼」則會把它殺掉。
- 請把
prefers-reduced-motion當成一等要求, 而不是事後補丁——這套語法必須能退化成瞬時的狀態切換,並且依然說得通。
動態是一個句子,不是一種情緒
介面動畫是一個關於因果的主張:這個面板是從那顆按鈕裡出來的;這一項去了那份清單;這次變化是因為你動手才發生的。 當動態承載其中某個主張時,使用者的心智模型會免費更新——不必閱讀,也不必推理。當它什麼都沒承載時,使用者就只能等這段編排跳完才能繼續,而每一次等待都是向信任課的一筆小稅。
順著這個視角,就能列出動態真正承擔的工作:
- 空間連續性——它從哪裡來,又去了哪裡。展開的卡片、從觸發點升起的浮層、朝封存圖示收攏的那一列被刪除的資料。
- 接收確認——你的按壓收到了。100毫秒的按鈕下沉、切換開關的甩動、核取方塊打上的那個勾。
- 注意力引導——狀態改變時,動起來的那個東西就是變了的那個東西。動態是介面能發出的最強注意力訊號之一;這也正是沒有理由的動態代價如此高昂的原因。
- 延遲掩蓋——骨架畫面的微光、樂觀更新的即時替換、讓400毫秒的請求顯得像是刻意安排而非出了故障的漸進呈現。
如果畫面上的某段動畫沒在做這四件事的任何一件,那它就是在做第五件:炫技。
四檔時長
時長不是品味問題,而是與注意力相配的物理。我用來要求每一個介面的檔位如下:
| 時長 | 用途 |
|---|---|
| 約100ms | 按鈕按下、切換開關、核取方塊——接收確認 |
| 150-200ms | 游標停留效果、淡入淡出、提示訊息 |
| 250-300ms | 展開/收合、手風琴、滑入面板 |
| 300-400ms | 頁面轉場、模態視窗、整個畫面的變化 |
底下的規律是:時長隨變化的幅度而定。 用來確認按壓的控制項必須近乎即時——超過約150ms,確認就會被讀成延遲。整個畫面的轉場可以慢一些,因為使用者需要這點時間重新定位。最常見的失敗是這層關係被顛倒過來:400ms 彈跳的按鈕(延遲偽裝成愉悅),以及100ms 生硬彈出的模態視窗(迷失方向偽裝成迅速)。
超過400ms,介面動態就需要一個格外充分的理由才配存在。新手引導的時刻與慶祝狀態偶爾配得上500-600ms;手機尺度的導覽幾乎從不如此,不過大螢幕上的容器變形是個誠實的例外——平板與桌機介面確實有理由拉長到500ms,因為視線要走的距離更遠。使用者會把你的轉場跑上幾千遍——在展示時迷人的編排,到了第三週就是他們咒罵的摩擦。
以彈簧為基礎的系統(SwiftUI、Framer Motion)把時間表達為剛性與阻尼,而非固定時長,但這些檔位依然成立:它們描述的正是你所調校的那個感知上的穩定時間。換一套記法,語法照舊。
兩條緩動規則
緩動是動畫取得物理感的地方,而兩條規則幾乎就夠用了:
進入用 ease-out。 抵達畫面的元素起步快、隨後減速就位——它們是在著陸。ease-out 把位移前置,眼睛因此更早捕捉到終點,元素也就顯得反應靈敏。
離開用 ease-in。 退場的元素加速遠去——它們帶著意圖離開。緩慢的起步給了眼睛一拍時間,先註記到確實有東西要走了,然後它才走。
linear 緩動讀起來很機械,因為物理世界裡沒有任何東西是這樣運動的;把它留給進度指示——那裡恆定的速率本身就是資訊——以及純粹的不透明度或顏色淡變,那裡沒有位移,也就沒有可供曲線塑形的運動。而對稱的 ease-in-out 屬於兩條規則刻意留白的第三種情況:留在畫面上移動的元素,例如重新排序的列,或改變尺寸的面板。它們既不著陸也不退場,所以從靜止中加速,再重新沉回靜止。ease-in-out 之所以聲名不佳,是因為它被當成進場與退場未經審視的預設值,同時讓抵達顯得遲鈍、讓離開顯得突兀。
刪除測試的實際操作
讓一套動態系統保持誠實的審查流程:
- 把介面上的每一段動畫都清點一遍——包括那些沒人刻意挑選的框架預設值。
- 逐條把這句話補完:「這段動態告訴使用者 ___。」 空間來源、接收確認、注意力、延遲——四者取其一,用白話說清楚。
- 補不出來的,討論一輪之後照樣補不出來。 「它增添了質感」「它顯得高級」只是換了套詞彙的空白。把這段動態刪掉,盯著介面看上一天;只存在於動態裡的質感,本來就不是質感。
- 把活下來的動畫按檔位計時、修正緩動,並測試減弱動態的路徑。
prefers-reduced-motion必須產出一個完全連貫、由瞬時狀態切換構成的介面——如果拿掉某段動畫會讓人看不懂,那這段動畫承載的資訊本來就也應該以靜態形式存在,這本身就是一項發現。
在一個成熟產品上跑一遍,清單裡通常有一半會死。某一輪審查得到的一份典型處決名單:卡片上400ms 的游標停留浮起(游標變化沒告訴使用者的,它一樣沒告訴)、每次導覽都重播一遍的清單錯峰進場(用600毫秒宣布「我們這裡有幾列資料」)、不停脈動的儲存圖示(要走了注意力,卻沒有任何變化值得注意)。沒有人會想念它們。留下來的部分變得更快、更一致,而且反而更顯眼——因為動態一旦不再是背景雜音,就重新取回了訊號價值。
系統視角
在設計系統裡,動態和間距、色彩一樣屬於 token:命名的時長(--motion-press: 100ms、--motion-surface: 300ms)、命名的緩動(--ease-enter、--ease-exit),以及取用 token 而非就地發明時間參數的元件。沒有被系統化的動態,失敗方式不是難看,而是漂移——五個模態視窗有五種時長,每一種都說得通,合起來卻毫無章法。管住間距刻度的那套紀律,同樣管住動態刻度:每個值要麼來自系統,要麼帶著一條寫下來的理由。
動態也是設計系統裡最易腐壞的一層——貢獻者最先擅自發揮的地方,因為一個一次性的250ms 補間感覺無傷大雅。它確實無傷大雅,一直到第十一次;然後產品就開始以十一種沒有動機的運動口音閃爍。這套語法只在刪除測試持續運行的期間才站得住。
常見問題
UI 動畫應該持續多久
讓時長對應變化的幅度:控制項的接收確認(按下、切換)約100ms,游標停留與淡入淡出150-200ms,展開/收合250-300ms,頁面轉場與模態視窗300-400ms。超過400ms需要格外充分的理由——使用者會把介面轉場重複上千次。
UI 動畫應該用什麼緩動
進入的元素用 ease-out(起步快、減速就位),離開的元素用 ease-in(加速遠去),留在畫面上移動的元素用 ease-in-out。linear 請留給進度指示以及純粹的不透明度或顏色淡變。在進場時,linear 讀起來很機械,ease-in-out 又會讓抵達顯得遲鈍——規則就是 ease-out。
介面究竟什麼時候才該使用動畫
當動態承載了靜態變化無法承載的資訊時:空間連續性(某個東西從哪裡來、去了哪裡)、對輸入的接收確認、把注意力引向發生變化之處,或者掩蓋無法避免的延遲。如果說不出一段動畫在做上述哪一件事,就把它移除——裝飾性的動態會向它觸及的每一次互動課稅。
prefers-reduced-motion 在動態系統中處於什麼位置
作為一等要求:減弱路徑以瞬時的狀態切換取代位移,而介面必須依然完全可理解。如果拿掉某段動畫會讓人看不懂,代表這段動態承載的資訊需要一個靜態的等價物——這既是一項無障礙發現,也是一項設計發現。