如何使用 CSS 实现导航栏中仅显示当前悬停菜单项的子菜单

通过精准控制 css 选择器与 `overflow` 属性的作用范围,可实现仅在鼠标悬停指定主菜单项时显示其对应子菜单,避免其他子菜单意外展开。关键在于将 `overflow: hidden` 从父级菜单容器移至每个独立的 `.sub-menu` 元素上。

要实现“仅显示当前悬停主菜单项的子菜单”,核心在于隔离子菜单的可见性控制逻辑,而非依赖父容器统一裁剪。常见错误是将 overflow: hidden 应用于整个 .menu 容器(如导航栏 ul),这会导致所有子菜单被强制隐藏,而悬停触发时又因缺乏精确作用域,引发多个子菜单同时显示。

✅ 正确做法是:

  • 为每个
  • 初始状态设为 opacity: 0、visibility: hidden、height: 0 或 max-height: 0(推荐 max-height 配合过渡);
  • 悬停 .menu-item 时,仅对其内部的 .sub-menu 应用 max-height: 300px(或足够容纳内容的值)、opacity: 1、visibility: visible。

以下是精简可靠的 HTML + CSS 示例:

.menu {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
}

.menu-item {
  position: relative;
}

.menu-item > a {
  display: block;
  padding: 12px 20px;
  text-decoration: none;
}

/* 关键:子菜单独立控制 */
.sub-menu {
  list-style: none;
  margin: 0;
  padding: 0;
  position: absolute;
  top: 100%;
  left: 0;
  background: #fff;
  min-width: 200px;
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
  border-radius: 4px;
  overflow: hidden; /* ✅ 移至此处,而非 .menu 上 */
  max-height: 0;
  opacity: 0;
  visibility: hidden;
  transition: 
    max-height 0.3s ease-out,
    opacity 0.2s ease,
    visibility 0.2s;
}

.menu-item:hover .sub-menu {
  max-height: 300px; /* 设为合理上限(避免过渡失效)*/
  opacity: 1;
  visibility: visible;
}

.sub-menu li a {
  display: block;
  padding: 10px 16px;
  color: #333;
  text-decoration: none;
}

.sub-menu li a:hover {
  background-color: #f5f5f5;
}

⚠️ 注意事项:

立即学习“前端免费学习笔记(深入)”;

  • max-height 过渡需设定明确数值(不能用 auto),否则 CSS 无法计算过渡路径;若子菜单高度差异大,可预估最大可能高度(如 max-height: 400px);
  • overflow: hidden 必须保留在 .sub-menu 上,确保 max-height 裁剪生效;
  • 若使用 display: none/block,则无法添加 CSS 过渡效果——应优先选用 visibility + opacity + max-height 组合;
  • 在移动端需额外处理点击展开(本例聚焦纯 CSS 悬停,适用于桌面端;响应式场景建议配合 JavaScript 增强交互)。

总结:问题本质是 CSS 作用域误用。修正的关键不在于新增复杂逻辑,而是将 overflow: hidden 精准下放到每个 .sub-menu 元素,再结合 :hover 伪类定向激活,即可实现干净、可维护、无干扰的单子菜单展开效果。