css菜单展开收起动画需用max-height替代height,因auto值无法插值;必须设具体像素值(如400px),配合:checked与兄弟选择器控制,js动态读scrollheight可实现精准适配。

用 :checked 控制同级菜单展开,核心是结构约束
必须把 <input type="checkbox"> 放在菜单内容元素的**前一个兄弟位置**,且两者共处同一父容器内。CSS 的 :checked 只能通过相邻兄弟选择器(+)或通用兄弟选择器(~)影响后续同级元素,无法跨层、无法反向、不能选父或子。
常见错误是把复选框塞进按钮里、或放在菜单后面——这时样式完全不会触发。
-
<input>和<div class="menu-content"> 必须是同级,且 <code><input>在前 - 若菜单内容是
<ul></ul>,它得紧接在<input>后面,中间不能插其他标签(除非用~) - label 标签可包裹文字或图标,但 for 属性必须精准匹配 input 的 id
- 收起状态:设
max-height: 0+overflow: hidden - 展开状态:用
.menu-checkbox:checked ~ .menu-content { max-height: 400px; },400 是预估最大高度(比如 8 行文字 × 行高 48px ≈ 384px) - 别设
max-height: 1000px:Safari 和部分安卓 WebView 会因插值帧过多导致卡顿,甚至跳变 - 如果内容高度变化大(比如含图片或动态加载项),纯 CSS 方案会失准,此时得切 JS 读
scrollHeight - label 上加
aria-expanded="false",点击后 JS 动态改值;或者用[aria-expanded="true"]配合:checked模拟(需 label 与 input 绑定) - 菜单内容容器加
aria-hidden="true",展开时改为"false" - 图标旋转建议用
transform: rotate(0deg) / rotate(180deg),别用 width/height 动画,性能差且易抖动 - 临时修复:展开前移除该 transform 类,动画结束再加回(用
transitionend监听) - 长期方案:把硬件加速移到 wrapper 层,菜单容器本身保持普通文档流
- 验证方法:在 Safari 开发者工具中手动删掉 transform 声明,刷新看 scrollHeight 是否恢复正常
- 注意:这个坑只在真机或 Safari 模拟器里暴露,Chrome DevTools 里测不出来
max-height 过渡失效?别写 auto,也别瞎设 1000px
写 transition: max-height 0.3s 却没动画,大概率是因为用了 max-height: auto——浏览器根本不认这个值做过渡。必须用具体像素值,且要「够大但不过量」。
箭头图标旋转、无障碍支持,不是锦上添花而是刚需
只靠 max-height 切换,用户不知道当前是展开还是收起。用 ::before 或 ::after 加个箭头,并配合 transform: rotate(180deg) 是最轻量的反馈方式。但更关键的是 ARIA 属性——没有它,屏幕阅读器无法告知用户菜单状态。
移动端 Safari 的 scrollHeight 失效?先查 transform 干扰
如果你在展开逻辑里用了 JS 读 element.scrollHeight,但在 iOS Safari 上返回 0 或 NaN,大概率是父容器或自身加了 transform: translateZ(0)、will-change: transform 或 transform: scale(1) ——这些会创建独立渲染层,导致 scrollHeight 计算异常。











