一個正確的 CSS cubic-bezier() 緩動函式,是一個語法上有效的宣告,其兩個 x 座標皆保持在封閉的 0–1 範圍內,其曲線從進度 (0, 0) 開始並在 (1, 1) 結束,且其取樣輸出的進度在每個經過的輸入時間比例上,皆符合你實際想要的時間節奏。CSS Cubic Bezier Generator 會為你強制執行這份契約:x1 與 x2 會被限制在 CSS 規定的必要範圍內,y1 與 y2 接受介於負十到十之間的有限數值,曲線在每個輸出取樣點使用有界的牛頓迭代加上二分搜尋回退來求解,並將該宣告序列化成一個完整的 transition-timing-function 陳述式,且結尾帶有分號。
cubic-bezier 緩動函式由剛好四個控制座標所定義:x1、y1、x2、y2。曲線錨定在起點 (0, 0) 與終點 (1, 1),而這些錨點是由 CSS 規範所固定,而非由作者自行設定。你所提供的這四個數字,描述了兩個中間控制點 P1 與 P2 的位置,它們會將曲線拉成介於錨點之間的形狀。接著每個瀏覽器會在動畫的每個瞬間,以 t 作為曲線參數(而非經過時間),代入參數化公式 B(t) = (1−t)3·P0 + 3(1−t)2·t·P1 + 3(1−t)·t2·P2 + t3·P3,以判斷動畫值目前已推進到多遠。
將 t = 0 代入參數化公式可得 B(0) = 1·(0,0) + 0 + 0 + 0 = (0, 0),而將 t = 1 代入可得 B(1) = 0 + 0 + 0 + 1·(1,1) = (1, 1)。光是這個代入,就足以證明本文其餘部分所倚賴的性質——無論你挑選哪些控制點,瀏覽器所接受的所有 cubic-bezier 曲線,皆從零進度開始,並結束於完整進度。

瀏覽器所強制執行的兩項有效性規則
CSS(由 W3C CSS Easing Functions Level 1 規範所定義)對 cubic-bezier() 設有剛好兩條有效性規則,而瀏覽器會以靜默方式套用這些規則。一旦違反任一規則,該時間函式便會變成無效,瀏覽器會回退為預設的緩動函式——通常是 ease——且不會顯示任何警告。
規則一:x1 與 x2 必須落在封閉的 0 到 1 範圍內。它們描述了緩動圖表水平軸上的輸入時間位置,因此只要其中一個滑出該範圍,瀏覽器便會認定整個宣告無效。CSS Cubic Bezier Generator 透過在介面層級限制 x 輸入,並在序列化前獨立驗證這些數值,來避免此情況發生,因此你無法因為輸入錯誤的數字而不小心送出一個無效的緩動函式。
規則二:y1 與 y2 必須是有限數值,但它們並不限制在 0–1 之內。y 值描述的是輸出進度,可以延伸到零以下或一以上,這正是產生預期(anticipation)與超出(overshoot)效果的原因。產生器的介面接受介於負十到十之間的有限 y 值,這個範圍已足以涵蓋幾乎所有實際的緩動需求,同時也不會讓手誤悄悄通過。
若你的目標是讓動作俐落地落在目標位置,請將兩個 y 值都保持在 0–1 之內。若你想要某個控制項在結束前先越過終點再回穩,可將 y2 推高到一以上。若你希望該值從靜止位置就先偏離再被拉回,則可將 y1 推到零以下。這兩種做法都是有效的 CSS;它們感覺起來是否恰當,則取決於你的實際介面需求。
使用 CSS Cubic Bezier Generator 來產生並稽核一條曲線
- 開啟 CSS Cubic Bezier Generator 並選擇一個起點。你可以點選五個關鍵字按鈕(linear、ease、ease-in、ease-out、ease-in-out)中的任一個,以載入標準化的控制點;或直接輸入你自己的 x1、y1、x2 與 y2 數值。選擇關鍵字並不會直接輸出該關鍵字本身;產生器會公開所有四個數字,如此一來,該緩動函式便能在沒有隱藏預設值的情況下被記錄、比較與修改。
- 檢視正方形圖表,以了解 (0, 0) 到 (1, 1) 之間的曲線形狀。圖表維持一個穩定的 0–1 框線,以便一般性的時間曲線能以視覺方式相互比較,但刻意取極端的 y 值會延伸到可見正方形之外——那個延伸的部分仍屬於曲線的一部分。動畫預覽與數值取樣使用的是實際計算出的緩動函式,而非裁切後的版本,因此即使圖表上看起來曲線被限制在框內,超出量仍會出現在這些輸出中。
- 讀取 0、0.25、0.5、0.75 與 1 這五個輸入對應輸出的取樣值。這些是求解器對執行階段唯一重要問題的回答:在給定這個比例的經過時間下,動畫值已推進到多遠?這些取樣值是使用有界的牛頓迭代加上二分搜尋回退計算出來的,因此輸入 0.5 時所得到的值反映的是曲線上實際的 x = 0.5 座標,而非曲線參數 t = 0.5。
- 點選 Run,以一個 900 毫秒的 transform 轉場(使用精確的產生緩動函式字串),切換預覽圓圈在兩個水平位置之間。反覆點選可讓你比較正向與反向的動態。預覽僅展示時間節奏——它並無法證明在實際介面中,一旦距離、屬性與持續時間改變後,曲線會帶來什麼樣的感覺。
- 點選 Copy CSS,將完整的 transition-timing-function 宣告(含結尾的分號)寫入剪貼簿。若你的瀏覽器拒絕存取剪貼簿,該宣告仍會保持可見且可選取,且狀態不會顯示成功,因此你隨時都可以手動複製。
- 將該宣告貼到你自己的樣式表中,並在你打算實際出貨的屬性、距離與持續時間下進行測試。若結果看起來仍然不對,可參考 在產生 CSS cubic bezier 時避免常見錯誤 這篇指南,它會逐一檢視最可能的肇因。
像稽核員一樣閱讀圖表、取樣與預覽
一個正確的緩動函式,不僅僅是一個瀏覽器會接受的宣告——它必須是在每個輸入時間比例上,都能產生你所預期時間節奏的宣告。產生器的三項輸出能讓你在正式採用之前,先稽核這份契約。
正方形圖表回答的是「這條曲線是什麼形狀?」它繪製了從 (0, 0) 到 (1, 1) 的參數化曲線,而五個標準化的關鍵字預設會在圖表中產生容易辨認的形狀:linear 是筆直的對角線,ease 會在末端輕微彎曲,ease-in 緊貼底部,ease-out 緊貼頂部,而 ease-in-out 則對稱地呈現 S 形曲線。若你自訂的控制點未產生你預期的形狀,圖表便是最快能顯示「哪裡出了問題」的訊號。
數值取樣回答的是更實用的執行階段問題:在給定比例的時間經過後,動畫值已推進到多遠?針對每個輸入 0、0.25、0.5、0.75 與 1,求解器會找出 x 座標符合該輸入的曲線參數,然後在該參數下求 y 的值。一個常見的混淆,是誤以為 0.5 的取樣代表「曲線參數 t 等於 0.5 時的 y 值」。實際上並非如此——CSS 使用的是 x 軸上的輸入進度,而曲線參數與輸入進度只有在 x1 = 0 且 x2 = 1(也就是線性情況)時才會相等。產生器的求解器在每個取樣點都反算 x 對 t 的對應關係,正是這項區分讓這張表格在控制點將曲線拉離對角線時依然值得信賴。
動畫預覽回答的是「在執行階段,這個感覺對嗎?」一個 900 毫秒的 transform 轉場,套用精確的緩動函式字串到一個移動的圓圈上,便是對於同一個字串在真實元件中會呈現效果的緊密近似。若預覽出現明顯的超出、急遽的折返,或收尾過於緩慢,那麼在 0.75 與 1 的取樣中就已經會顯示相同的行為——預覽只是讓它變得更加直觀。數字只有在序列化為可見的宣告時,才會四捨五入到小數點後三位,因此內部運算保留了完整的 JavaScript 數值精度,取樣值不會累積四捨五入的誤差。
產生器視為參考資料的關鍵字對應
當你點選任一個關鍵字按鈕時,產生器會載入由 CSS Easing Functions Level 1 所定義的控制點,並以可見宣告中的四個數字呈現,而不是直接輸出該關鍵字本身。這代表你從預設值所建立的每個緩動函式,都能在沒有隱藏預設值的情況下被記錄、比較與修改,而這些關鍵字對應同時也作為經過測試的參考案例,讓你能用來確認此工具是否正確地求解曲線。
| 關鍵字 | x1 | y1 | x2 | y2 |
|---|---|---|---|---|
| linear | 0 | 0 | 1 | 1 |
| ease | 0.25 | 0.1 | 0.25 | 1 |
| ease-in | 0.42 | 0 | 1 | 1 |
| ease-out | 0 | 0 | 0.58 | 1 |
| ease-in-out | 0.42 | 0 | 0.58 | 1 |
這些精確的數字來自 W3C 規範,且另外記載於 MDN 的 cubic-bezier() 參考文件。當你點選對應的關鍵字按鈕時,若你的產生器輸出與這些列中的某一列相符,你便能確定求解器、序列化器與四捨五入規則皆如預期運作。任何不一致都是立即調查的訊號,切勿在調查前信任此工具所產生的任何自訂曲線。
Test the declaration in the real interface before shipping
A declaration that audits clean on the generator can still feel wrong in production because cubic-bezier() describes only the timing function — not the property, distance, duration, delay, or surrounding motion. The generator deliberately limits its scope to transition-timing-function so the output stays predictable and easy to audit, and does not produce keyframes, spring physics, linear() stop lists, steps(), duration, delay, iteration count, or a full transition shorthand.
When you paste the declaration into your real stylesheet, test it with the same property the animation will actually animate, at the same distance it will travel, for the same duration the user will experience. A 900 ms transform transition looks different from a 200 ms opacity transition at the same easing, and a 50 pixel slide looks different from a 400 pixel slide. Watch focus behavior while the element is transitioning, and confirm pointer events still land where users expect them to land. Large overshoots can make controls appear to reverse, leave their container, or reveal content that was expected to remain clipped, so verify the visual outcome rather than assuming the easing alone is enough.
Respect reduced-motion preferences. A technically correct easing is not automatically appropriate for every user. If animation is not essential to the interaction, give users who prefer reduced motion a fallback that skips or shortens the transition. All calculation in the generator runs locally in your browser — no curve, CSS, or interaction data is uploaded, stored, or sent to an animation service — which makes it safe to experiment with sensitive control points without sending work outside the page.
Related reading: Make Sure You Generate a CSS Toggle Switch Correctly.