max-height 配合 overflow: hidden 是最实用、兼容性好且无需 JS 的动画方案;需合理设起止值(0→具体像素)、正确触发重排、同步过渡 padding/margin、保障无障碍与移动端体验。

用 max-height 配合 overflow: hidden 是最实用、兼容性好且无需 JS 就能生效的方式。关键不是“设个值就行”,而是起止值要合理、时机要准确、样式要配合。
为什么 max-height 是首选
height 不能设为 auto 做过渡,display 完全不可动画,而 max-height 是连续可插值的 CSS 属性。只要内容被 overflow: hidden 截断,浏览器就能平滑拉伸或收缩视觉高度。
- 起始值写
max-height: 0,结束值不能写none(会失效),得是具体像素值 - 静态内容可预估安全上限,比如
max-height: 420px(比最长内容多出 20–30px) - 动态内容(如接口返回、含图片/字体)必须用 JS 读
element.scrollHeight后赋值
避免卡顿和跳变的关键操作
直接写 el.style.maxHeight = '400px' 再加类,动画常不触发——因为浏览器没来得及重排。正确顺序是:
- 先加状态类(如
.open),让样式规则就位 - 立刻执行
el.offsetHeight(强制同步重排) - 再设
el.style.maxHeight = el.scrollHeight + 'px' - 收起时反向操作:先设目标高度,再移除类,最后在
transitionend中清空内联max-height
样式细节决定是否“丝滑”
只过渡 max-height 不够,padding、margin、border 变化会视觉脱节:
- 给内容区统一用
padding,但父容器别设 padding,避免过渡冲突 - 避免
border和box-sizing: content-box同时存在,否则边框参与高度计算导致抖动 - 推荐写法:
transition: max-height 0.3s ease, padding 0.3s ease, margin 0.3s ease - 必须始终搭配
overflow: hidden,且该声明要写在共用基础类里,不是只加在 .open 中
无障碍与移动端适配
光有动画不够,用户还得点得准、听得清:
- 标题区域建议用
<button>或加role="button",确保键盘可聚焦、回车可触发 - 同步更新
aria-expanded(true/false)和aria-controls(指向内容 ID) - 移动端点击热区要够大,整行响应;iOS Safari 的 300ms 延迟可通过
touch-action: manipulation或 fastclick 类库消除 - 收起后建议加
pointer-events: none,防止动画未结束时重复点击


















