如何实现 HTML 下拉菜单中的嵌套子菜单(二级下拉)

本文详解如何在纯 html + css 实现响应式、无 javascript 的二级下拉菜单(dropdown submenu),基于 hover 触发,支持层级展开与精确定位,并提供可直接运行的完整代码示例。

要为现有下拉菜单添加嵌套子菜单(即“二级菜单”),关键在于利用 CSS 的相邻兄弟选择器(+)和 :hover 状态联动控制显示逻辑,而非依赖 JavaScript。原结构中 .dropdown-content 仅包含 标签,无法承载子菜单;我们需要将某一项(如第一个 level_1)设为触发点,并在其后紧跟一个 .sub-1 容器作为子菜单——这样当鼠标悬停在该链接上时,CSS 可精准定位并显示其后的子菜单块。

以下是优化后的完整实现(已整合响应式适配):

  
  
    
    level_1 (has submenu)
    
      level_11
      level_12
      level_13
    

    
    level_1
    level_1
  

对应的核心 CSS(含基础样式与子菜单逻辑):

/* 基础下拉容器 */
.dropdown {
  display: inline-block;
  position: relative; /* 关键:为绝对定位子元素提供参照 */
}
#myDropdown {
  display: inline-block;
  vertical-align: -3.3px;
}

.dropdown .dropbtn {
  border: none;
  outline: none;
  color: #0F4391;
  padding: 8.5px 15px;
  background-color: inherit;
  font-family: inherit;
  cursor: pointer;
}

.dropdown-content,
.sub-1 {
  display: none;
  position: absolute;
  background-color: #f9f9f9;
  min-width: 160px;
  box-shadow: 0 8px 16px rgba(0,0,0,0.2);
  z-index: 1;
  border-radius: 4px;
}

/* 子菜单默认左对齐,右侧展开(推荐) */
.sub-1 {
  left: 100%; /* 紧贴父菜单项右侧 */
  top: 0;
  margin-left: 0; /* 覆盖原示例中的 magic margin */
}

.dropdown-content a,
.sub-1 a {
  color: #0F4391;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
  text-align: left;
  white-space: nowrap;
}

/* 悬停高亮 */
.dropdown-content a:hover,
.sub-1 a:hover {
  background-color: #e0e0e0;
  color: #000;
}

/* 主菜单悬停显示一级菜单 */
.dropdown:hover .dropdown-content {
  display: block;
}

/* 关键逻辑:

当第一个菜单项被悬停时,显示其后紧邻的 .sub-1 */ .dropdown-content a:nth-child(1):hover + .sub-1 { display: block; } /* 响应式:小屏下改为垂直堆叠,禁用悬停(改用点击/JS 或折叠) */ @media screen and (max-width: 600px) { .dropdown-content, .sub-1 { position: static; /* 取消绝对定位,适应流式布局 */ width: 100%; } .dropdown-content a:nth-child(1):hover + .sub-1 { display: none; /* 移动端建议隐藏子菜单或改用 JS 展开 */ } }

注意事项与最佳实践

  • HTML 结构必须严格保持 a + .sub-1 相邻关系,否则 + 选择器失效;
  • .sub-1 应使用 position: absolute 并通过 left: 100% 实现向右展开,比 margin-left 更可靠且可维护;
  • 避免在 .sub-1 中再嵌套三级菜单(.sub-2),因 CSS 无法跨多层 + 连续选择(如 a:hover + .sub-1 + a:hover + .sub-2 不合法),如需多级,建议引入轻量 JS 或使用 :has()(现代浏览器支持,但兼容性有限);
  • 移动端体验需额外处理:纯 CSS hover 在触摸设备上不可靠,生产环境建议配合媒体查询 + 小屏 JS 切换逻辑(例如点击展开/收起);
  • 所有链接建议添加 tabindex="0" 并补充键盘导航支持(focus 状态样式),以满足无障碍访问(a11y)要求。

通过以上方案,你即可在零 JS 依赖下构建清晰、稳定、语义合理的二级下拉导航,兼顾桌面端交互流畅性与移动端基础可用性。