Flex布局不负责折叠,只负责排列;动画需用max-height+overflow:hidden实现,.submenu应设flex-direction:column且避免flex:1,DOM结构须确保input与.submenu同级兄弟。

Flex布局本身不负责折叠,只管排列
很多人一看到“树形菜单+Flex”,就下意识给 .submenu 加 flex-basis 或写 transition: flex-basis 0.3s,结果动画完全不动。这是因为 flex-basis 是参与 flex 计算的初始尺寸,不是渲染后可插值的视觉属性,浏览器直接忽略它的 transition。
真正要动的是高度变化:必须用 max-height + overflow: hidden 控制展开收起,Flex 只负责把子项排成列、换行或对齐。
-
.submenu应设display: flex; flex-direction: column;,确保内部菜单项垂直堆叠 - 别给
.submenu设flex: 1或flex-grow: 1,否则它会被父容器强行拉伸,破坏max-height的控制边界 - 若子项含图标+文字组合,建议统一用
flex: 0 0 auto防止被压缩变形
:checked ~ .submenu 失效,90%是DOM结构不对
CSS 的 ~ 选择器只匹配「同一父元素下、位于 input 后面的所有兄弟元素」,不是后代,也不是任意位置的同名元素。常见翻车点:
-
<input id="node-1"><label for="node-1">文档</label><ul class="submenu">...</ul>✅ 正确:三者同级,input在最前 -
<label><input>...</ul></label>❌ 错误:ul变成label的后代,~完全不生效 - HTML 中换行/空格文本节点会卡住
+,但~仍可用——所以一律用~,别贪图+ - 多级嵌套时,每层
.submenu都必须由独立的<input id="node-1-2">控制,父级checked状态不会穿透影响子级
max-height 动画总卡半截?预估值和 overflow 是关键
写 max-height: 0; → max-height: 300px; 看似简单,但实际中常出现菜单展开到一半突然停住、或者内容撑破容器弹出来。核心原因只有两个:
立即学习“前端免费学习笔记(深入)”;
- 漏了
overflow: hidden:这是最高频错误。没有它,max-height过渡时内容直接溢出,像被暴力拽出来 -
max-height值太小:300px 对短菜单够用,但一旦子项含图片、动态插入的徽标、或字体缩放,实际高度可能超 400px。保守做法是设500px,或 JS 读取scrollHeight后注入样式 - 别用
height: auto做过渡目标值——浏览器无法插值 “auto”,动画直接跳变 - 如果
.submenu内部用了flex: 1的占位项(比如搜索框),它会强行拉高容器,导致max-height被突破;应改为flex: 0 0 auto并加min-height: 0
子菜单定位偏移、堆在左上角?缺 position: relative
当 .submenu 用 position: absolute 定位(如 top: 100%; left: 0;)时,它会向上查找最近的「已定位祖先」作为参考系。如果每个 .menu-item 都没设 position: relative,那所有子菜单都会以 <body> 为锚点,全部挤在页面左上角。
- 必须给每个带子菜单的
.menu-item显式加position: relative - 如果一级项宽度不均(如“首页” vs “产品中心”),又想让二级菜单水平居中,纯 CSS 的
left: 50%; transform: translateX(-50%);可能因字体渲染差异漂移,这时得用 JS 获取getBoundingClientRect()动态计算 -
.submenu自身也要设box-sizing: border-box,否则 padding 和 border 会额外增加高度,让max-height过渡终点不准
max-height 刚好包住一切,又不浪费一像素空间。


















