纯CSS二级下拉导航桌面端可行、移动端必须用JS或checkbox模拟;父级li必须设position:relative,子ul须为li直接子元素且用position:absolute+top:100%紧贴,hover链中断主因是间隙或定位缺失。

纯 CSS 能做出可用的二级下拉导航,但桌面端和移动端必须分开对待——桌面靠 :hover 可行,移动端仅靠 CSS 几乎必然失效。
父级 li 必须设 position: relative
这是最常被忽略的定位前提。如果一级菜单项 li 没有显式设置 position: relative,它的子级 ul 会相对于最近的已定位祖先(甚至 body)定位,导致下拉菜单飘到页面任意角落。
-
ul必须是li的直接子元素(即li > ul),不能隔层(如li > div > ul) - 若一级菜单用了
display: flex,flex容器本身不创建定位上下文,仍需在每个li上加position: relative - 父容器若有
transform或overflow: hidden,会截断或错位下拉菜单,需检查是否意外创建了新层叠上下文
:hover 链必须连续、无间隙
鼠标一移开就消失,不是 bug,是 :hover 的自然行为:它只作用于当前悬停的元素。一旦路径中断(比如 li 和 ul 之间有 1px 空隙),就会触发 mouseout。
- 二级
ul必须用position: absolute; top: 100%紧贴父li底边;哪怕多出 1px 边框或margin,都可能断开悬停链 - 避免给
li设line-height或padding-bottom撑开视觉空隙;必要时用margin-top: -1px补偿 - 不要依赖
:focus-within做核心逻辑——iOS Safari 对它的支持仍不稳定
移动端无法仅靠 :hover 可靠工作
触屏设备没有持续 hover 状态,手指抬起即失焦。:active 或 :focus 模拟只会造成闪退、卡死或点不到第三级。
立即学习“前端免费学习笔记(深入)”;
- 推荐用
input[type="checkbox"] + label结构:点击label触发input:checked,再用:checked ~ .submenu控制显示 - 如果项目已用 Bootstrap 5,默认启用 Popper.js,二级
ul可能被重定位;加data-bs-popper="none"到该ul上禁用自动计算 - 真机测试不可省:iPad 上点开二级菜单后手指一松就收起,这种问题模拟器完全暴露不了
z-index 和层叠上下文容易误配
菜单盖不住模态框、三级菜单飘左上角……八成是 z-index 生效范围错了。
-
z-index只对已定位元素生效(position是relative/absolute/fixed/sticky);光写z-index: 999不设position是无效的 - 一级菜单设
z-index: 100、二级101、三级102就够;堆高值(如9999)反而让后期调试更难 - 父容器若含
overflow: hidden或transform,会创建新层叠上下文,子元素的z-index只相对父级生效,而非全局
真正麻烦的从来不是怎么写出来,而是上线前只在桌面 Chrome 测过——结果 iPad 用户根本点不开二级菜单,这种问题必须在真机触屏环境下验证。


















