cubic-bezier() 不能直接存入 CSS 变量,因 CSS 变量仅作字符串替换,而 transition-timing-function 需原生函数语法;需用 @keyframes 绑定贝塞尔曲线并通过 animation 简写调用。

cubic-bezier() 不能直接存进 CSS 变量里——你写 --ease-bounce: cubic-bezier(0.17, 0.89, 0.32, 1.28);,再用 transition-timing-function: var(--ease-bounce);,浏览器不会解析,只会当普通字符串处理,最终静默降级为 ease。
为什么 var(--ease) 在 transition-timing-function 中无效
CSS 变量本质是字符串替换,不是运行时求值。即使你存了合法的 cubic-bezier(0.17, 0.89, 0.32, 1.28),var(--ease) 展开后仍是纯文本,而 transition-timing-function 只接受原生函数语法,不接受字符串字面量。
DevTools 会报 warning:“Invalid property value”,或完全不报错、只回退;Chrome 动画检查器里曲线图显示为直线,就是没生效的明确信号。
用 @keyframes + animation 简写绕过限制
这是目前最稳定、兼容性最好的方案(Chrome 43+/Safari 9+/Firefox 16+),核心是把贝塞尔曲线绑定到命名动画上,再用变量控制动画名:
- 定义空
@keyframes,仅设animation-timing-function(加opacity等无影响属性防被优化):@keyframes ease-bounce { 0% { opacity: 0.99; } 100% { opacity: 1; } } - 在
:root中用变量存完整animation值::root { --anim-bounce: ease-bounce 0.6s cubic-bezier(0.17, 0.89, 0.32, 1.28) forwards; } - 调用时直接赋给
animation:.btn { animation: var(--anim-bounce); }
注意:不能拆成 animation-name: var(--anim-name); animation-timing-function: var(--ease); ——后者依然无效。
立即学习“前端免费学习笔记(深入)”;
cubic-bezier() 参数越界时的真实行为
参数必须全在 [0, 1] 范围内才可靠,越界不是“更酷”,而是失效:
-
y1或y2超出[0, 1](如cubic-bezier(0.2, -0.1, 0.8, 1.3)):Chrome/Firefox/Safari 全部静默降级为ease,动画变成默认缓动 -
x1或x2略超(如1.05)可能被容忍,但不保证跨浏览器一致,且规范未定义 - 想模拟弹性效果?别硬填负数或超 1 的
y值——用@keyframes手动写多段关键帧,或 JS 计算,cubic-bezier()不是物理引擎
调试时打开 Chrome DevTools → Animations 面板,点时间曲线预览图:如果显示为直线而非曲线,说明贝塞尔参数没生效。
需要 JS 动态生成缓动函数时怎么办
如果必须在运行时根据参数计算插值(比如拖拽调节控制点),用 JavaScript 实现 cubicBezier(p1x, p1y, p2x, p2y) 函数更可控:
function cubicBezier(p1x, p1y, p2x, p2y) {
const cx = 3 * p1x;
const bx = 3 * (p2x - p1x) - cx;
const ax = 1 - cx - bx;
const cy = 3 * p1y;
const by = 3 * (p2y - p1y) - cy;
const ay = 1 - cy - by;
return function(t) {
const x = t * (cx + t * (bx + t * ax));
let t0 = t;
for (let i = 0; i < 8; i++) {
const x2 = t0 * (cx + t0 * (bx + t0 * ax));
const dx = cx + t0 * (2*bx + 3*ax*t0);
t0 -= (x2 - x) / dx;
}
return t0 * (cy + t0 * (by + t0 * ay));
};
}然后传给 requestAnimationFrame 或 GSAP 等库;CSS 变量做不到这点,它只负责静态声明。
真正麻烦的不是怎么写,而是记住:CSS 变量 ≠ JS 变量,它不执行、不解析、不校验。所有“看起来像函数”的值,都得靠浏览器在声明位置原生识别——这决定了你能塞进去的,永远只是字符串,不是逻辑。


















