因为 height: auto 无法参与 css 过渡,浏览器无法计算“auto”的具体像素值导致跳变;而 max-height 是可动画的数值属性,设足够大的固定值(如500px)即可实现平滑折叠动画。

为什么用 max-height 而不是 height 做折叠动画
因为 height: auto 无法参与 CSS 过渡(transition),浏览器不知道“auto”对应的具体像素值,动画会直接跳变。而 max-height 是可动画的数值属性,只要设一个足够大的固定值(比如 max-height: 500px),就能让内容在“视觉上”展开或收起。
注意这个“足够大”必须大于面板内所有可能内容的高度,否则会展开不全;但也不能过大(比如设成 9999px),否则动画时间拉得太长、响应迟钝。
- 常见错误:写
height: 0; height: auto+transition→ 动画失效,只有显示/隐藏切换 - 正确思路:用
max-height模拟高度变化,配合overflow: hidden隐藏溢出 - 兼容性:所有现代浏览器都支持
max-height过渡,IE10+ 也 OK
基础 HTML 结构与关键 CSS 类名
结构要语义清晰,建议用
作为备选(原生支持,但样式难控),日常开发更常用
内容区域
核心控制逻辑在 .accordion-content 上:
立即学习“前端免费学习笔记(深入)”;
- 默认收起:设
max-height: 0+overflow: hidden - 展开状态:加类名如
.is-open,改max-height为预估最大值(如500px) - 过渡必须写在
.accordion-content上:transition: max-height 0.3s ease-in-out
transition 时间和缓动怎么调才自然
太快(0.1s)像抽搐,太慢(0.6s)显卡顿。0.25–0.35s 是多数 ui 的舒适区间。
缓动推荐 ease-in-out 或 cubic-bezier(0.34, 1.56, 0.64, 1)(稍带弹性感),避免用 linear —— 它会让展开开头和结尾都显得生硬。
- 别把
transition写在.is-open类里(只作用于进入),应始终写在基础类(如.accordion-content)上,确保收起时也有动画 - 如果内容高度差异大(比如有的面板只有 2 行,有的有 10 行),统一用
max-height: 500px可能导致短内容收起时“拖尾”,这时可考虑 js 动态计算真实高度(但会增加复杂度)
JavaScript 控制开合时容易漏掉的细节
纯 CSS 方案只能靠 :checked + 隐藏 checkbox,灵活性差;实际项目基本要用 JS 绑定点击事件。关键点不在“加类”,而在“类切换时机”:
- 先加
.is-open,再强制重排(offsetHeight),再设置max-height→ 否则动画不触发 - 收起时不能直接删类,得先设
max-height为当前高度,再用setTimeout延迟删类,否则会瞬间消失 - 多个面板同时操作时,注意避免事件冒泡或重复绑定(比如用
Event.currentTarget而非event.target)
最简健壮写法是:展开前读取 scrollHeight,设为 max-height,动画结束后再设回 none 或 0 —— 这样不管内容多高都准,只是略增加 JS 量。