推荐使用自定义 cubic-bezier(0.2, 0.8, 0.4, 1),它比预设值更可控,开头稍缓、中段加速、末尾带轻微过冲再回正,避免卡顿与硬切;height: auto 不可过渡,应改用 max-height 或 transform: scaley() 等方案。

transition-timing-function 选 cubic-bezier 还是预设值?
绝大多数点击展开菜单的“弹性感”不是靠 ease-in-out 或 ease 实现的,而是用自定义 cubic-bezier(0.2, 0.8, 0.4, 1) 模拟弹簧回弹前段——它比预设值更可控,且不会像 ease-out 那样在末尾突然变慢、显得卡顿。
-
cubic-bezier(0.2, 0.8, 0.4, 1)是最常用的安全弹性起点:开头稍缓、中段加速、末尾带轻微过冲再回正,视觉上自然 - 避免用
steps()或linear做展开动画,它们完全没弹性,用户感知就是“硬切” - 别直接抄
cubic-bezier(0.175, 0.885, 0.32, 1.275)这类强弹跳值——它适合图标微动,用在菜单高度变化上容易晃眼、失焦
height: auto 无法 transition?得换思路
CSS 的 transition 对 height: auto 完全无效,这是初学者踩坑最多的地方。浏览器无法计算 auto 的终点数值,所以动画会直接跳变。
- 方案一(推荐):改用
max-height+ 合理上限值,比如max-height: 500px,再配overflow: hidden - 方案二:用
transform: scaleY()配合origin-top,但需注意子元素内联样式或绝对定位可能错位 - 方案三:JavaScript 测量真实高度后设为具体
height值,再触发 transition——更准但多一步 DOM 查询
点击触发时菜单闪一下?检查 overflow 和初始状态
菜单第一次展开常伴随 1 帧闪烁,根源往往是 overflow: hidden 和初始 height/max-height 不匹配。
- 确保默认状态是
max-height: 0+overflow: hidden,而不是height: 0单独控制 - 如果菜单里有图片或字体加载延迟,
max-height设太小会导致内容被截,建议按行高 × 最大行数估算,留 20% 余量 - 不要在
:hover上写展开逻辑——点击菜单需要明确的.is-open类控制,否则移动端 touch 事件不响应
移动端点击无反馈?加 touch-action 和 will-change
iOS Safari 和部分安卓 WebView 对纯 CSS 展开动画响应迟钝,尤其嵌套在滚动容器里时,本质是渲染线程未被提前告知要优化。
- 给菜单容器加
touch-action: manipulation,告诉浏览器这个区域只做点击/切换,禁用双指缩放等干扰行为 - 展开前临时加
will-change: max-height(注意:只在触发时加,动画结束立刻移除,否则长期占用内存) - 避免在
@media (prefers-reduced-motion: reduce)下仍强制播放弹性动画——应降级为transition: none或极短0.1s线性过渡
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











