You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:将垂直菜单hover展开改为点击展开并实现max-height过渡

纯CSS实现点击展开的垂直菜单(带过渡效果)

嘿,好消息——纯CSS完全能实现这个需求,根本不需要JavaScript!我给你两种靠谱的方案,都能实现点击展开+max-height过渡的效果,你可以根据自己的需求选:

方案1:用原生<details>标签(语义化+最简实现)

HTML5的<details>和<summary>是原生的可折叠控件,自带点击展开/收起的功能,我们只需要加一点CSS就能实现过渡动画:

HTML结构

<nav class="vertical-menu">
  <details class="menu-item">
    <summary>主菜单1</summary>
    <ul class="submenu">
      <li><a href="#">子菜单1-1</a></li>
      <li><a href="#">子菜单1-2</a></li>
      <li><a href="#">子菜单1-3</a></li>
    </ul>
  </details>
  <details class="menu-item">
    <summary>主菜单2</summary>
    <ul class="submenu">
      <li><a href="#">子菜单2-1</a></li>
      <li><a href="#">子菜单2-2</a></li>
    </ul>
  </details>
</nav>

CSS样式

/* 基础样式重置(你可以结合自己的原有样式调整) */
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  border-radius: 8px;
}
body {
  font: 16px/1.5 sans-serif;
  padding: 20px;
}

.vertical-menu {
  width: 200px;
  background: #f5f5f5;
}

.menu-item {
  margin: 4px 0;
  padding: 0 8px;
}

/* 自定义主菜单样式 */
.menu-item summary {
  padding: 10px 0;
  cursor: pointer;
  list-style: none; /* 去掉默认的三角符号 */
}
/* 添加自定义展开/收起图标 */
.menu-item summary::after {
  content: '▼';
  float: right;
  transition: transform 0.3s ease;
}
/* 展开时旋转图标 */
.menu-item[open] summary::after {
  transform: rotate(180deg);
}

/* 子菜单过渡核心 */
.submenu {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
  padding-left: 20px;
}
/* 展开时设置足够大的max-height(覆盖子菜单实际高度即可) */
.menu-item[open] .submenu {
  max-height: 200px;
}

.submenu li {
  padding: 8px 0;
}
.submenu a {
  text-decoration: none;
  color: #333;
}

方案2:用隐藏Checkbox实现(更灵活的定制)

如果你需要更灵活的样式控制,或者要兼容极少数不支持<details>的老浏览器,可以用隐藏的checkbox配合CSS兄弟选择器实现:

HTML结构

<nav class="vertical-menu">
  <div class="menu-item">
    <label for="menu1" class="menu-title">主菜单1</label>
    <input type="checkbox" id="menu1" class="menu-toggle">
    <ul class="submenu">
      <li><a href="#">子菜单1-1</a></li>
      <li><a href="#">子菜单1-2</a></li>
      <li><a href="#">子菜单1-3</a></li>
    </ul>
  </div>
  <div class="menu-item">
    <label for="menu2" class="menu-title">主菜单2</label>
    <input type="checkbox" id="menu2" class="menu-toggle">
    <ul class="submenu">
      <li><a href="#">子菜单2-1</a></li>
      <li><a href="#">子菜单2-2</a></li>
    </ul>
  </div>
</nav>

CSS样式

/* 基础样式重置同上 */
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  border-radius: 8px;
}
body {
  font: 16px/1.5 sans-serif;
  padding: 20px;
}

.vertical-menu {
  width: 200px;
  background: #f5f5f5;
}

.menu-item {
  margin: 4px 0;
  padding: 0 8px;
  position: relative;
}

.menu-title {
  padding: 10px 0;
  cursor: pointer;
  display: block;
}
.menu-title::after {
  content: '▼';
  float: right;
  transition: transform 0.3s ease;
}

/* 隐藏checkbox,只通过label触发 */
.menu-toggle {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* 选中checkbox时的样式变化 */
.menu-toggle:checked ~ .menu-title::after {
  transform: rotate(180deg);
}

.submenu {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
  padding-left: 20px;
}

.menu-toggle:checked ~ .submenu {
  max-height: 200px;
}

.submenu li {
  padding: 8px 0;
}
.submenu a {
  text-decoration: none;
  color: #333;
}

关键说明

  • 两种方案的核心都是用max-height过渡:因为height: auto无法直接过渡,所以我们给子菜单设置max-height: 0(收起状态)和一个足够大的max-height(展开状态),配合overflow: hidden就能实现平滑的展开/收起动画。
  • 如果需要实现「只能展开一个菜单」的互斥效果,那确实需要一点JavaScript来控制,但如果只是单个菜单独立展开/收起,纯CSS完全够用。

内容的提问来源于stack exchange,提问作者Sowmya Kaparthi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:38:02