cubic-bezier(0.68,-0.55,0.27,1.55)能做出弹出感是因为先反向收缩再过冲回弹,模拟物理蓄力;y₁/y₂需在[-0.5,2.0]内否则降级;侧边栏动画必须用transform而非width;height:auto无法过渡,需用max-height或JS测量;须适配prefers-reduced-motion和移动端兼容性。

为什么cubic-bezier(0.68, -0.55, 0.27, 1.55)能做出弹出感
它不是“更弹”,而是让动画先反向收缩(y₁ = -0.55 1),最后回落——这模拟了物理上的蓄力+过冲+回弹。纯ease-in-out全程在[0,1]内插值,永远不超调,也就没有“弹”的错觉。
但注意:y1和y2必须落在[-0.5, 2.0]区间内才被稳定支持;超出如y2=3.0,Chrome会静默降级为linear,Safari可能直接截断为1,动画就废了。
验证方法:打开Chrome DevTools → Animations面板,点开timing function预览图——若显示为直线,说明已降级。
侧边栏弹出该用transform还是width
必须用transform: translateX(),别碰width。
立即学习“前端免费学习笔记(深入)”;
width动画触发layout + paint,尤其含图片或阴影时,肉眼可见卡顿;transform走合成器线程,稳60fps。
典型错误写法:transition: width 0.4s cubic-bezier(0.68,-0.55,0.27,1.55);——曲线再准也没用,性能先崩。
正确结构示例:
.sidebar {
width: 300px;
transform: translateX(-300px);
transition: transform 0.4s cubic-bezier(0.68,-0.55,0.27,1.55);
will-change: transform; /* 动画开始前加,结束后立刻移除 */
}
.sidebar.open {
transform: translateX(0);
}额外提醒:display: none状态下无法触发动画,得先设display: block再加class,否则直接跳变。
菜单展开时height: auto为啥动不了
浏览器根本算不出height: auto的终点值,transition直接失效,结果就是“啪”一下弹出来。
三个可行替代方案:
- 用
max-height代替:设一个安全上限(比如max-height: 500px),配合overflow: hidden;估算时按行高×最大行数+20%余量,避免截断 - 用
transform: scaleY():需设transform-origin: top,但要注意子元素绝对定位或内联样式可能偏移 - JS测量真实高度:先
getBoundingClientRect().height,再设具体height值触发过渡——准,但多一次DOM查询
别在:hover里写展开逻辑,移动端touch事件不响应;要用.is-open类控制,配合JS切换。
弹性动画最容易被忽略的细节
不是参数调得狠不狠,而是交互上下文是否匹配。
prefers-reduced-motion: reduce下仍硬上弹性动画,对部分用户是视觉干扰,应降级为transition: none或0.1s线性过渡。
移动端iOS Safari对transform硬件加速支持不稳定,尤其嵌套滚动容器中;加touch-action: manipulation可提升响应优先级。
真正决定“像不像弹”的,不是贝塞尔数值,而是关键帧节奏与位移幅度的匹配——比如translateY(40px)对小图标太猛,对卡片又不够,得实测微调,每次±2px比大改有效。


















