html如何制作一个简洁的多级侧边导航菜单并不只看表面做法,关键还要理解相关条件、限制和后续影响。
最稳妥的多级菜单实现是用 ul/li 嵌套配合隐藏 checkbox + label:每级子菜单为独立 ul 嵌在父 li 内,checkbox 控制 display 切换,padding-left 与 border-left 实现层级缩进,移动端用 @media 强制收起子菜单并确保点击热区。
浏览器原生支持嵌套 ul,语义清晰、无障碍友好、无需 JS 就能展开收起(配合 :checked + <input type="checkbox">)。比纯 CSS :hover 更可靠——:hover 在触摸设备上会失效,且无法记忆展开状态。
关键点:
ul,嵌在父 li 内部<input type="checkbox" id="menu-1"> 控制对应 ul 的显隐,通过 label[for] 关联点击区域display: none,勾选后改为 display: block(不用 visibility 或 opacity,否则仍占布局空间或无法聚焦)避免 JS 不是偷懒,而是降低耦合、提升首屏加载速度和 SSR 可用性。核心是把 checkbox 当作“状态开关”,label 作为“触发按钮”:
<li> <input type="checkbox" id="sub-1"> <label for="sub-1">设置</label> <ul class="submenu"> <li><a href="/setting/profile">个人资料</a></li> <li><a href="/setting/notify">通知偏好</a></li> </ul></li>
对应 CSS:
input[type="checkbox"] { display: none; }.submenu { display: none; }input[type="checkbox"]:checked ~ .submenu { display: block; }
注意:~ 是通用兄弟选择器,要求 .submenu 必须紧跟在 input 后面(中间不能有其他元素),所以 label 要紧挨着 input,ul 紧跟在 label 后。
别用 margin-left 或绝对定位做缩进——会导致焦点框错位、屏幕阅读器朗读混乱。正确做法是统一用 padding-left 增加内边距,并为不同层级加不同颜色的左侧竖线增强可读性:
padding-left: 1rem,border-left: 2px solid #e0e0e0
padding-left: 2.5rem,border-left: 2px solid #c5c5c5
padding-left: 4rem,border-left: 2px solid #aaa
这样缩进值是累加的,视觉层级一目了然,且不会影响 tab 键顺序或焦点位置。
小屏幕下多级展开会严重挤压内容区,必须强制收起所有子菜单,只留一级可见:
@media (max-width: 768px) { .submenu { display: none !important; } input[type="checkbox"] { display: inline-block; }}
这里 !important 是必要的——它覆盖掉 :checked ~ .submenu 的显示规则,确保折叠态优先。同时把 checkbox 显式设为 inline-block,方便用户手动勾选(否则在移动端可能点不到)。
真正容易被忽略的是:子菜单里的链接在移动端要保留可点击性,不能因为 display: none 就让它们完全不可达。所以得额外给 label 加 cursor: pointer 和足够点击热区(最小 44×44px),否则手指点不准。