如何在不使用display:none时关闭已激活项并激活新项
搞定无display:none的导航互斥激活问题
嘿,我瞅了你的代码和需求——要实现点击新导航项时自动关闭已激活的项,还不能用display:none对吧?你的现有代码用toggleClass只能切换当前点击项的状态,但没法联动关闭其他已激活的项,这就会出现多个导航项同时亮着的情况。我来给你改改,完美适配你的需求:
核心思路
不用display:none的前提下,要实现互斥激活,关键是点击新项时先全局清除所有激活状态,再给当前项加上激活类,同时联动处理子菜单的显示/隐藏——毕竟你用了visibility和过渡动画来控制显示,咱就顺着这个路子来,不碰display:none。
修改后的完整代码
HTML部分(顺便修复语义化问题:ul的直接子元素必须是li)
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <div class='subBkgd'></div> <div class='nav'> <ul id='menu'> <li><a href='#'>HOME</a></li> <li class='sub'> <a href='#'>DESIGNS ></a> <ul> <li><a href='#'>item1</a></li> <li><a href='#'>item2</a></li> <li><a href='#'>item3</a></li> </ul> </li> <li class='sub'> <a href='#'>CUSTOMIZE ></a> <ul> <li><a href='#top'>item5</a></li> <li><a href='#colors'>item6</a></li> </ul> </li> <li class='sub'> <a href='#'>FROM SCRATCH ></a> <ul> <li><a href='#top'>item7</a></li> <li><a href='#'>item8</a></li> </ul> </li> </ul> </div>
CSS部分(保留你的过渡逻辑,优化子菜单显示)
.subBkgd { display: block; visibility: hidden; position: absolute; width: 10px; height: 20px; margin: 20px auto 0; background-color: rgba(0, 0, 0, .4); transition: transform .25s ease-in-out!important; z-index: -10; } .subChange { visibility: visible!important; transform: scaleX(200); } .nav ul { display: flex; width: 80%; justify-content: space-between; text-align: center; list-style: none; padding: 0; } .nav ul li { font: 400 .75em Verdana, sans-serif; white-space: nowrap; height: 20px; width: 15%; transition: background .25s ease-in-out; padding: 5px 0; cursor: pointer; } .nav ul ul { visibility: hidden; display: flex; margin-top: 10px; padding: 0 2%; position: absolute; background: #fff; list-style: none; } .nav ul ul li { width: auto; } .nav ul ul a { padding: 0 20px; } .navChange { background-color: #666; } .navChange a { color: #F00!important; text-decoration: none; } .ulChange { visibility: visible!important; opacity: 1!important; }
JavaScript部分(核心修改,实现互斥逻辑)
$(document).ready(function() { // 处理导航项点击事件 $('.nav li').on('click', function(e) { e.stopPropagation(); // 阻止事件冒泡,避免子菜单点击误触发父元素关闭 const isSubItem = $(this).hasClass('sub'); const isAlreadyActive = $(this).hasClass('navChange'); // 第一步:全局清除所有激活状态 $('.nav li').removeClass('navChange'); $('.subBkgd').removeClass('subChange'); $('.sub ul').removeClass('ulChange'); // 第二步:如果点击的不是已激活的项,就激活它;如果是已激活的sub项,就保持关闭状态 if (!isAlreadyActive) { $(this).addClass('navChange'); // 如果是带下拉的sub项,同步打开子菜单 if (isSubItem) { $('.subBkgd').addClass('subChange'); $('ul', this).addClass('ulChange'); } } }); // 可选:点击子菜单里的项时,不关闭当前导航的激活状态 $('.nav ul ul li').on('click', function(e) { e.stopPropagation(); }); });
关键改动说明
- 互斥逻辑实现:放弃原有的
toggleClass,改为先全局移除所有激活类,再给当前项添加,确保同一时间只有一个导航项处于激活状态 - 事件冒泡处理:添加
e.stopPropagation(),避免点击子菜单时误触发父元素的关闭逻辑 - 语义化修复:把原代码里直接放在ul中的a标签改成li包裹,符合HTML规范,避免潜在的样式/行为异常
- 子菜单优化:给子菜单加了绝对定位和背景色,让下拉显示更合理(你可以根据自己的UI需求调整)
这样就完全实现了你的需求:点击新导航项时自动关闭之前激活的项和子菜单,激活新项;点击已激活的项则关闭它的状态,全程没用到display:none。
内容的提问来源于stack exchange,提问作者Cardguy
相关产品推荐
相关产品推荐

