果冻弹性感纯css实现需用transform+特定贝塞尔曲线:进入用cubic-bezier(0.175,0.885,0.32,1.275)实现超调回弹,退出用cubic-bezier(0.6,-0.28,0.735,0.045),起始scale不能为0,避免top/left触发重排,配合will-change优化ios动画。

用 transform + transition-timing-function 模拟果冻弹性感
纯 CSS 实现“果冻回弹”效果,本质是避开物理引擎,靠贝塞尔曲线伪造弹性惯性。关键不是加动画,而是选对缓动函数——cubic-bezier(0.175, 0.885, 0.32, 1.275) 是最接近果冻拉伸-回弹节奏的组合,比 ease-out 更有张力,又比 spring()(仅 Safari 支持)更通用。
注意:这个贝塞尔值会让元素先轻微“超调”(比如模态框放大到 105% 再缩回 100%),形成视觉上的弹性反馈。别用 ease-in-out,它太匀速,没果冻感。
- 只对
transform和opacity做动画,避免触发布局重排(top/left会强制重排) - 模态框容器必须设
will-change: transform,否则 iOS Safari 动画可能卡顿 - 不要在
:hover上直接写这个贝塞尔——鼠标移入移出太快,容易中断动画导致错乱
模态框显示/隐藏时的 class 切换逻辑
果冻效果依赖“进入”和“退出”两个阶段使用不同贝塞尔曲线。进用 cubic-bezier(0.175, 0.885, 0.32, 1.275)(带超调),退用 cubic-bezier(0.6, -0.28, 0.735, 0.045)(反向回弹,避免生硬收尾)。
示例结构:
.modal {
opacity: 0;
transform: scale(0.9);
transition: opacity 0.4s cubic-bezier(0.6, -0.28, 0.735, 0.045),
transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.modal.is-open {
opacity: 1;
transform: scale(1);
}
- 务必把
transition写在默认状态(.modal),而不是.is-open,否则关闭时无动画 -
scale(0.9)起始值不能是0,否则贝塞尔超调会失效(0 → 0 的 scale 无法超调) - 如果模态框有遮罩层(
.modal-overlay),它的opacity动画要用线性或简单缓动,别跟主体抢焦点
移动端 Safari 的 spring() 函数能用吗?
能,但只限 iOS 17+ / macOS Sonoma+ 的 Safari,且不支持回退动画。写成 transition-timing-function: spring(1, 100, 10, 0) 确实更接近真实弹簧,但一旦用户用 Chrome 或旧版 Safari 打开,就退化成 ease,果冻感全无。
- 生产环境建议降级方案:用
@supports (transition-timing-function: spring(1, 100, 10, 0))包一层,里面覆盖贝塞尔值 -
spring()的四个参数含义是(质量, 刚度, 阻尼, 初始速度),调参成本高,一个项目里改三次就晕了 - 别在
transform: translateZ(0)后加spring(),某些 iOS 版本会触发渲染 bug,白屏一闪
为什么加了贝塞尔还是像“橡皮筋”不是“果冻”?
因为果冻的核心是形变+恢复,而纯 scale 只有缩放。真果冻感需要轻微扭曲感——可以加极小量的 skewY(1deg) 或 rotate(0.5deg) 配合 scale,在峰值帧短暂出现再归零。
例如:
.modal.is-open {
transform: scale(1.02) skewY(-0.8deg);
}
.modal {
transform: scale(0.95) skewY(0.3deg);
}
- 偏移量必须控制在 ±1deg / ±3% 以内,超过就变“抽搐”,不是果冻
- 不要对圆角元素(
border-radius)做skew,边缘会糊,尤其在低分辨率安卓机上 - 如果模态框内有文字,
skew会导致文字倾斜失真,此时宁可放弃这点扭曲,保可读性
果冻感的上限不在代码多复杂,而在人眼是否注意到那 0.3 秒里的微妙形变——调参时盯着动画循环看 10 遍,比查文档管用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











