重力动画必须用transform而非top/left,因后者触发layout+paint导致卡顿,前者由GPU加速且不重排;需配合cubic-bezier模拟重力加速度,并用scaleY与box-shadow增强物理感。

重力动画必须用 transform 而不是 top/left
直接修改 top 或 left 触发的是 layout + paint,动画卡顿明显,尤其在低端设备上掉帧严重。浏览器对 transform 的 translateY() 有硬件加速支持,且不触发重排。
错误写法:
div { top: 0; animation: fall 0.8s ease-out; }<br>@keyframes fall { to { top: 200px; } }
正确做法:用 transform: translateY() 模拟下落位移,并配合 cubic-bezier(0.25, 0.46, 0.45, 0.94) 模拟真实重力加速度曲线(类似 Material Design 的标准缓动)。
- 避免用
px绝对值——改用vh或视口相关单位,适配不同屏幕高度 - 若需“落地反弹”,不要硬写多个
keyframes阶段,用animation-timing-function: steps(1, end)分段 + 多个transform组合更可控 - 注意:Safari 对
cubic-bezier()支持良好,但旧版 iOS WebKit 在will-change: transform缺失时可能偶发闪烁,建议显式加上
如何让元素“砸地”后产生微小形变?
CSS 本身无法模拟真实物理形变,但可用 scaleY() + transform-origin: bottom 实现可信的压缩-回弹效果。关键不是“多像”,而是节奏感:压缩要快(0.05s),回弹略慢(0.15s),并带轻微 overshoot。
立即学习“前端免费学习笔记(深入)”;
示例关键帧:
@keyframes squash {<br> 0% { transform: translateY(0) scaleY(1); }<br> 70% { transform: translateY(5px) scaleY(0.92); }<br> 100% { transform: translateY(0) scaleY(1.03) translateY(-2px); }<br>}
-
transform-origin: bottom确保缩放以底部为锚点,否则会“漂浮” - 回弹终点加
translateY(-2px)是为了抵消视觉上“弹太高”的错觉,人眼对垂直位移敏感 - 慎用
scaleX()—— 水平拉伸易破坏布局流,除非容器明确设了overflow: hidden
为什么 animation-play-state: paused 不能替代 JS 控制时机?
纯 CSS 动画一旦触发就按时间轴跑完,paused 只能暂停,无法“等元素进入视口再启动”或“检测碰撞后触发反弹”。真实重力场景常依赖运行时状态:比如滚动中掉落、与其他元素碰撞、或根据设备倾斜角调整方向。
- 用
IntersectionObserver监听元素是否进入可视区,再给元素加class启动动画,比animation-delay更可靠 - 需要“落地即停+随机微偏移”时,CSS 无法生成随机数,必须用 JS 设置
style.transform = translateX(${Math.random() * 4 - 2}px) - 移动端陀螺仪数据(
deviceorientation)只能由 JS 读取,CSS 无对应钩子
阴影与模糊如何增强“物理存在感”?
真实物体下落时,离地面越近,投影越实、越宽、越不透明;同时边缘因空气扰动略带动态模糊。CSS 中靠 box-shadow 和 filter: blur() 协同实现,但要注意性能陷阱。
- 投影用多个
box-shadow层叠:近处用0 4px 6px rgba(0,0,0,0.15),远处加一层0 12px 24px rgba(0,0,0,0.08) - 模糊必须用
will-change: filter提前声明,否则 iOS Safari 滚动时会突然闪白 - 绝对禁止在动画中频繁切换
filter: blur(2px)→blur(0),会导致每帧重绘;改用opacity控制模糊层显隐更稳
质感不来自参数堆砌,而在于位移、缩放、投影三者的节奏同步——差 0.03 秒,人眼就感觉“假”。调试时关掉所有颜色,只看灰度和运动轨迹,反而更容易发现问题。


















