transition 用在 height 上无效是因为 height 从 0 到 auto 无法计算具体像素值,导致浏览器直接跳变;应改用 max-height、transform 或 opacity 等可过渡属性实现丝滑动画。

transition 用在 height 上为什么没效果
因为 height 从 0 到 auto 无法过渡——浏览器不知道 auto 对应的具体像素值,直接跳变。
- 改用
max-height:设一个足够大的固定值(比如max-height: 500px),再配合transition: max-height 0.3s ease - 初始状态设
max-height: 0+overflow: hidden,展开时设为500px - 如果菜单项高度差异极大,500px 不够就调高;太大会导致收起时有延迟感
用 transform 或 opacity 替代 height 的取舍
更稳妥的丝滑方案是避开尺寸过渡,改用视觉属性:
-
transform: scaleY(0)→scaleY(1),配合transform-origin: top模拟下拉感 -
opacity: 0+visibility: hidden→opacity: 1+visibility: visible,适合淡入淡出 - 注意:
transform和opacity是 CSS 合成属性,GPU 加速友好,性能比height过渡好得多 - 但
scaleY会压缩子元素文字,需在子元素上加transform: scaleY(1)抵消
JavaScript 控制展开/收起时的关键时机
纯 CSS 可以做 hover 展开,但点击切换必须 JS;容易卡顿或错位,往往是因为时机不对:
- 别在
click后立刻加展开类,先offsetHeight强制触发重排,再加类 - 收起时,监听
transitionend事件再移除内容(否则可能 DOM 还在、动画已停) - 移动端要额外处理
touchstart,避免 300ms 延迟导致点击无响应 - 示例关键行:
menu.offsetHeight; menu.classList.add('open');
兼容性与无障碍的隐藏代价
丝滑动画常以牺牲可访问性为代价,这点容易被忽略:
立即学习“前端免费学习笔记(深入)”;
-
max-height: 0+overflow: hidden会让屏幕阅读器读不到内容,得配aria-expanded和aria-hidden -
transform: scaleY(0)仍占用文档流位置,可能影响焦点顺序;display: none更干净但无法过渡 - Safari 对
transform过渡偶尔抽风,加will-change: transform可缓解 - 动画时间别低于
0.2s,太快人眼难感知;也别超过0.4s,否则交互拖沓
height 和 max-height 混用,或者忘了清掉 transition 导致后续操作连锁错乱。动画只是表层,状态同步和 DOM 生命周期才是真难点。


















