求助:将垂直菜单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
相关产品推荐
相关产品推荐

