不能用height: auto做折叠动画,因浏览器不支持auto值插值计算,transition直接失效;必须用max-height配合overflow:hidden和transition三者协同,设合理目标值(如320px)并同步更新aria属性保障可访问性。

为什么不能用 height: auto 做折叠动画
浏览器根本不会对 height: auto 做插值计算,transition 一写就失效——看起来加了 transition: height 0.3s,实际是直接跳变。Flex 容器里的子元素(比如 .nav-list)即使设了 flex-direction: column,也逃不开这个限制。这不是 Flex 的锅,是 CSS 动画机制本身不支持 auto 参与过渡。
max-height 过渡必须配 overflow: hidden
只写 max-height: 0 → max-height: 300px 不够,漏掉 overflow: hidden 就会出问题:
- 内容溢出容器,菜单项在收起状态仍部分可见
- 滚动条意外出现,破坏视觉一致性
- 动画末尾“卡顿”,因为浏览器还在渲染被裁切的内容
正确组合永远是:max-height + overflow: hidden + transition 三者同时存在,且 overflow: hidden 必须从初始状态一直保持到动画结束。
怎么选 max-height 的目标值才不卡顿也不截断
设太小:菜单项被硬截断,用户看不到完整内容;设太大:动画拖沓,尤其在低端安卓机上明显延迟。稳妥做法是按典型场景预估:
立即学习“前端免费学习笔记(深入)”;
- 5 个纯文本菜单项 →
max-height: 200px足够(行高约 40px × 5) - 含图标或短描述的 8 项 →
max-height: 320px更安全 - 桌面端详情面板 → 可配合媒体查询升到
max-height: 600px
别用 max-height: 100% 或 max-height: none,前者依赖父容器高度(通常没设),后者不可动画。
Flex 布局下容易忽略的可访问性细节
用 display: none 切换整个 <nav> 是错的——屏幕阅读器直接跳过,键盘 Tab 焦点断裂。正确做法是让 <nav> 始终在 DOM 中,只控制其子容器(如 .nav-list)的 max-height:
- 默认状态:
.nav-list { display: flex; flex-direction: row; } - 移动端折叠:
.nav-list { display: flex; flex-direction: column; max-height: 0; overflow: hidden; } - 展开时加类:
.nav-list.is-open { max-height: 320px; } - 同步更新
aria-expanded="true/false"和aria-controls,否则辅助技术无法感知状态变化
真正难的不是写出动画,而是让动画在 JS 关闭、低视力、触控、Safari 等所有真实场景里都不掉链子。预估高度只是起点,scrollHeight 动态读取才是应对复杂内容的兜底方案。


















