子菜单错位是因为grid上下文不继承,必须逐级显式声明display: grid;.submenu需设display: grid才能解析grid-column: 2;推荐固定三列轨道+显式列号定位;小屏应使用display: none控制显隐;父容器须设overflow: visible防裁剪。

为什么只给外层设 display: grid,子菜单就错位了
因为 Grid 上下文不继承——.submenu 里的 grid-column: 2 不会自动参考外层的列轨道,它需要自己也是 display: grid 才能解析这些属性。常见表现是子菜单堆在左上角、文字重叠、或完全不响应定位指令。
必须逐级显式声明:
-
.sidebar设display: grid和grid-template-columns: 240px 240px 240px - 每个可展开项(如
<li class="has-submenu">)需包裹一层<div class="submenu-wrapper">,并设 <code>display: grid -
.submenu自身也得设display: grid,否则grid-column: 2无效 - 顶层定义三列:
grid-template-columns: 240px 240px 240px - 一级菜单项默认占第 1 列:
grid-column: 1 - 二级菜单强制进第 2 列:
.submenu[data-level="2"] { grid-column: 2; } - 三级菜单进第 3 列:
.submenu[data-level="3"] { grid-column: 3; } - 小屏统一设:
@media (max-width: 767px) { .submenu { display: none; } } - 仅当前展开路径上的子菜单设为:
.submenu.active { display: grid; } - JS 展开时,同步清除同级其他
.submenu.active类,避免多级同时显示 - 别用
visibility: hidden或opacity: 0替代display: none——前者不释放空间,后者不阻断焦点 -
.sidebar必须加:overflow: visible - 若
.sidebar是 flex 子项,还要确认其父 flex 容器没设overflow: hidden - 不要依赖
z-index补救——裁剪发生在布局阶段,不是层叠问题
用 grid-column: 2 比 grid-column: span 2 更稳
span 看似省事,但嵌套层级一变就崩:二级菜单 span 2,三级再套一层变成 span 4,直接超出容器宽度,触发换行或溢出。固定列轨道 + 显式线号才是可控方案。
推荐写法:
小屏下隐藏子菜单不能只靠 grid-column
移动端把 .submenu 的 grid-column 改成 1,它依然在 DOM 中渲染、占空间、影响滚动和键盘焦点——屏幕阅读器能读到,Tab 键会卡住。
正确做法是媒体查询中彻底控制显隐:
父容器 overflow 漏设会导致子菜单被裁剪
子菜单横向铺开(比如从第 1 列伸到第 2 列)时,如果父容器(如 .sidebar)没设 overflow: visible,浏览器默认按 auto 或 hidden 处理,结果就是右边一半被切掉。
这个点容易被忽略,尤其当侧边栏本身被 flex 包裹时:
display: grid,或任一环节用错 display: none 的时机,整个分级逻辑就会静默失效。











