一個 CSS 的 cubic-bezier() 值,只要其中一個 x 控制點座標落於零到一的封閉區間之外,就會立即失效,而這正是在瀏覽器中自訂緩動曲線靜默失敗最常見的原因。當該值無效時,瀏覽器會忽略整個宣告並退回到預設的 ease 關鍵字,因此動畫仍會執行,但所採用的時間設定並非開發者原本預期的。其他問題則來自對曲線實際繪製內容的誤解:x 軸代表輸入時間,而 y 軸代表動畫值,並且曲線參數 t 並不等於經過的時間,只有在控制點對稱時才會相同。將 50% 的取樣誤讀為「在 t = 0.5 通過曲線的一半」,而非「時間過了一半」,就會產生明顯的不一致。即使是產生的曲線在技術上有效,也可能感覺不對——極端的 y 值會產生 overshoot(過衝),使內容超出其容器範圍,或者產生短暫反向後再穩定的 anticipation(預期)。疑難排解代表著先釐清上述哪一個問題正在發生,接著透過受控的輸入、數值取樣以及真實環境的預覽來驗證修正結果。

產生 CSS Cubic Bezier 時通常哪裡出錯
大多數的 cubic-bezier() 問題可以歸納為五種可辨識的模式,而辨識出屬於哪一種模式能大幅縮小修正範圍。
第一種,也是最常見的,就是超出範圍的 x 座標。CSS 規定只要 x1 或 x2 落在封閉區間 [0, 1] 之外,cubic-bezier() 值即為無效。瀏覽器不會提出警告,而是悄悄退回到預設的 ease 關鍵字。動畫仍會播放,但使用的時間設定並非你所撰寫的。
第二種是將曲線參數 t 與經過的輸入時間混淆。產生器中的數值取樣表會在輸入值 0、0.25、0.5、0.75 與 1 上顯示五個取樣點。由於 x 軸代表的是經過時間而非參數本身,因此除了對稱的控制點之外,表格中的 50% 那一列很少會剛好等於 t = 0.5 時的 y 值。將這兩者視為相同,正是「我的曲線與預期不符」這類回報的根源。
第三種是曲線雖然有效,但在實際使用中感覺不對。超出 [0, 1] 的 y 值會在零以下產生 anticipation,或在一以上產生 overshoot,而極端的數值可能會將控制點拉出其容器範圍、顛倒焦點順序,或與偏好減少動畫 (reduced-motion) 的設定產生衝突。
第四種是將宣告放在錯誤的 CSS 屬性上。寫在 @keyframes 內部的 cubic-bezier() 會被悄悄忽略;它必須放在 transition-timing-function 或 animation-timing-function 上,這樣計時函式才能被 transition 或 animation 引擎整體使用。
第五種是複製貼上的問題,亦即保留了前導的關鍵字而未採用完整的數值形式。CSS Cubic Bezier 產生器在選擇關鍵字後,一定會顯示全部四個數字,讓結果可以被記錄並修改,而不致隱藏預設值。
如何逐步修正 CSS Cubic Bezier 的問題
- 開啟 CSS Cubic Bezier 產生器,挑選一個標準的緩動預設值,或者直接輸入你已經使用的四個控制點座標。
- 確認產生器接受這些數值。x 輸入欄位會被限制在有效的 CSS 範圍內,因此任何超出範圍的 x 值都會在輸入階段就被拒絕,而不是產生一個悄悄無效的宣告。
- 查看在輸入值 0、0.25、0.5、0.75 與 1 時的數值取樣表。如果你在「通過一半時間」所預期的數值並沒有出現在 0.5 那一列,代表你可能思考的是曲線參數,而非經過時間。
- 按下 Run preview(執行預覽),觀察圓形以一段 900 毫秒的 transform transition(轉場),套用所產生的緩動函式。重複點擊以比較向前與向後的運動。
- 複製完整的宣告(包括尾端的分號),然後貼到實際元件的 transition-timing-function 或 animation-timing-function。
- 以實際的屬性、距離、持續時間以及 reduced-motion(偏好減少動畫)設定進行測試,因為預覽僅展示時間設定,並無法反映生產環境在各種工作負載下的真實效能。
為什麼 x1 與 x2 必須維持在零到一之間
根據 W3C 的 CSS Easing Functions Level 1 規範,x1 與 x2 是輸入時間的位置:用以描述兩個中間控制點在動畫中的相對位置。CSS 要求兩者都必須保留在封閉區間 [0, 1] 內,因為輸入時間必須單調地從零遞增到一,而 x 一旦超出這個範圍,曲線就會被迫在時間上迴退,這是計時模型無法表示的。其結果就是一個無效的 cubic-bezier() 值,而瀏覽器的退行為就是忽略整個宣告,改用 ease。
y 值的情況則不同。y 代表的是輸出進度,而非輸入進度,因此規範允許 y1 與 y2 超出 [0, 1]。負的 y1 會產生 anticipation——動畫值會短暫地反向最終方向移動;而大於一的 y2 則會產生 overshoot,也就是數值會越過最終位置再回穩。這兩者都是彈性或彈簧式運動的合法技巧,但極端數值仍應在實際介面中進行測試。CSS Cubic Bezier 產生器接受介於負十到十之間的有限 y 值,這涵蓋了任何實際可行的緩動意圖,同時避免產生瀏覽器可能拒絕的非有限數值。
有兩個外部來源可以確認這些限制:W3C CSS Easing Functions Level 1 定義了有效性規則,而 MDN 的 cubic-bezier() 參考資料 則記錄了瀏覽器端的退行行為,並提供了對應的範例。
為什麼 50% 的取樣並非 t = 0.5 時的值
在二維空間中的 cubic Bézier 曲線,是由一個從零到一的單一變數 t 所參數化。在 t = 0 時曲線位於進度 (0, 0);在 t = 1 時曲線則位於進度 (1, 1)。在這個範圍內,曲線會依據兩個控制點描繪出一條平滑的路徑。雖然很容易將曲線解讀為 t 代表經過時間,但實際上並非如此。瀏覽器以 x 軸上的輸入時間來驅動動畫,然後再查詢該 x 對應的 y 值。x 與 t 之間的對應關係,完全取決於控制點的擺放位置。
產生器會直接揭示這個差異。對於 0、0.25、0.5、0.75 與 1 的每個取樣輸入,求解器會先找出 x 座標符合所要求輸入的 t 值,再評估該 t 對應的 y。實作使用有界的牛頓迭代法 (Newton iterations),並在需要時退回到 bisection(對分搜尋),藉此避免將曲線參數誤當成經過時間的陷阱。這就是在控制點不對稱的情況下,輸入為 0.5 的那一列,與「t = 0.5 時的曲線」具有實質差異的原因。
若你想重現另一個工具所帶給你的感受,可以先查看取樣表中輸入 0.5 的那一列。該列回答了一個實務上的問題:當時間經過一半時,動畫值已經推進到什麼程度?
閱讀關鍵字對應表而不遺漏任何資訊
CSS 定義了五個緩動關鍵字,每個關鍵字都有對應的 cubic-bezier() 等效形式。下列數值來自 W3C CSS Easing Functions Level 1 規範,並在產生器中以可執行的參考資料形式保存。在介面中選擇關鍵字並不會輸出該關鍵字本身,而是載入四個對應的數字,讓宣告可以被記錄並調整。
| 關鍵字 | cubic-bezier(x1, y1, x2, y2) | 常見用途 |
|---|---|---|
| linear | cubic-bezier(0, 0, 1, 1) | 等速運動、載入進度條 |
| ease | cubic-bezier(0.25, 0.1, 0.25, 1) | 預設值,溫和地加速與減速 |
| ease-in | cubic-bezier(0.42, 0, 1, 1) | 緩慢開始,適用於離開畫面的元素 |
| ease-out | cubic-bezier(0, 0, 0.58, 1) | 快速開始,適用於進入畫面的元素 |
| ease-in-out | cubic-bezier(0.42, 0, 0.58, 1) | 對稱的緩慢開始與結束 |
如果你那「壞掉的」曲線是因為把關鍵字寫在錯誤的屬性上,請改用上表對應的數值形式,問題通常就會隨之消失。
在真實介面中測試所產生的曲線
產生器中 900 毫秒的 transform 預覽僅展示時間設定。它無法告訴你,這個緩動函式在頁面實際工作負載下的感受為何。距離、持續時間、被動畫化的屬性、該屬性的渲染成本、輸入裝置,以及周邊的運動狀態,都會改變對平滑性的主觀感受。一個有效的曲線並不必然代表它是可存取 (accessible)、高效能或合適的。
進行疑難排解時,請以候選的緩動函式,搭配最終的持續時間與屬性,來執行真實的元件。在元素進行 transition 時,檢查焦點與指標行為,因為運動可能會使焦點框移出畫面,或在動畫過程中攔截指標事件。請尊重 prefers-reduced-motion(偏好減少動畫):如果該動畫並非必要,當使用者請求減少動畫時,就應該將其移除或大幅縮短。若想進一步了解當曲線在工具中看起來正確,但在生產環境卻出錯時的復原方式,請參閱修正產生 CSS Cubic Bezier 後出現錯誤結果的問題。
在這個階段還會浮現另外兩個問題。第一個是瀏覽器退行:如果你發現時間設定與 ease 完全相同,儘管你寫了自訂的宣告,這時請檢查 x1 與 x2 是否都位於 [0, 1] 之內,並確認宣告是放在 transition-timing-function 或 animation-timing-function 上,而不是寫在 @keyframes 內部或錯誤的簡寫屬性上。第二個是剪貼簿存取被拒:若瀏覽器拒絕剪貼簿存取,產生器仍會將宣告保持為可見且可選取的狀態,因此手動複製依然有效,而狀態指示燈也不會誤顯示為成功。
當有效的曲線仍感覺不對時
有時候所有限制都符合,每個取樣也都在預期之內,但結果仍然感覺不對。在重新調整曲線之前,請先檢查三個位於 cubic-bezier() 宣告之外的因素。
第一個是持續時間。同一條曲線在 200 毫秒與 900 毫秒下的感受不同,因為對加速與減速的感知是與絕對時間相關的。第二個是被動畫化的屬性。transform 與 opacity 動畫成本低廉,且會在 compositor(合成器)上執行;而動畫 width、top 或 box-shadow 則會在每一幀觸發更多運算,並可能掩蓋你所選擇的緩動效果。第三個是互動情境。一個以 overshoot 開啟的選單,在 hover 時可能討喜,但在首次繪製時或在小螢幕上可能會令人感到不適。
當你猶豫不決時,請帶著一個明確的症狀回到產生器:「結尾過於激進」、「沒有 anticipation」、「沒有減速」。調整相關的控制點,觀察取樣表的變化,並在真實元件上重新測試。這個「診斷症狀、一次調整一個座標、在生產環境中驗證」的循環,正是多數 cubic-bezier() 疑難排解問題的實務解答。
延伸閱讀:CSS 切換開關的旋鈕行程距離如何計算。