如何实现点击减号时折叠Accordion手风琴并保留折叠动画
解决手风琴点击自身展开状态(减号)无法关闭的问题
我帮你找到了问题的核心所在,咱们一步步来修复:
问题根源
你的原JS代码里,不管点击的h3是不是已经处于展开状态,都会执行「关闭所有展开项 → 给当前项加opened类 → 展开当前项」的完整流程。这就导致点击已展开的项时,刚关闭就立刻重新展开,看起来像是没有反应。
另外你的HTML里存在h3嵌套h3的无效结构(HTML规范不允许标题标签嵌套),浏览器会自动修正这个结构,可能导致事件绑定或样式出现异常,需要一并调整。
修改后的完整代码
1. 修正后的HTML结构(移除标题嵌套)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="accordion"> <h3> <div> <h4>Vulputate ut pharetra sit amet aliquam id diam maecenas</h4> </div> </h3> <div> <p></p> <h1>Vulputate</h1> <p></p> <h1>Commodo sed egestas egestas</h1> <ul> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> </ul> <p></p> </div> <h3> <div> <h4>Blandit aliquam etiam erat velit scelerisque</h4> </div> </h3> <div> <p></p> <h1>Commodo sed</h1> <p></p> <h1>Pretium viverra suspendisse potenti</h1> <ul> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> </ul> <p></p> </div> <h3> <div> <h4>Pretium viverra suspendisse potenti</h4> </div> </h3> <div> <p></p> <h1>Pretium viverra suspendisse </h1> <p></p> <ul> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> <li>Pretium viverra suspendisse potenti</li> </ul> <p></p> </div> </div>
2. 调整逻辑后的JS代码
"use strict"; var animateTime = 500; $(".accordion > h3").click(function () { const $currentHead = $(this); const $currentContent = $currentHead.next("div"); // 核心:先判断当前项是否已经展开 if ($currentHead.hasClass("opened")) { // 如果已展开,直接关闭它 $currentHead.removeClass("opened"); $currentContent.stop().animate({ height: '0' }, animateTime); return; // 终止后续代码,避免重新展开 } // 如果未展开,先关闭所有已展开的项 $(".accordion > h3.opened").each(function () { const $elem = $(this); $elem.removeClass("opened"); $elem.next("div").stop().animate({ height: '0' }, animateTime); }); // 展开当前项 $currentHead.addClass("opened"); autoHeightAnimate($currentContent, animateTime); // 滚动到当前标题(保留原需求) setTimeout(function () { $("html, body").animate({ scrollTop: $currentHead.offset().top }, animateTime); }, animateTime); }); /* 自动高度动画函数(保留原逻辑) */ function autoHeightAnimate(element, time) { var curHeight = element.height(); var autoHeight = element.css('height', 'auto').height(); element.height(curHeight); element.stop().animate({ height: autoHeight }, time); }
3. CSS代码(无需修改,保留原样式)
.accordion > h3 { position: relative; font-size: 18px; height:60px; border-radius:8px; margin: 0 0 10px 0; cursor: pointer; line-height: 34px; background: #f1f2f3; color: #333; font-weight: 700; } .accordion > h3 div{padding:12px 0 0 70px !important;} .accordion > h3::before { content: '+'; border-radius:8px 0 0 8px; display: inline-block; position: absolute; width: 50px; height: 100%; left: 0; background: orange; color: #fff; font-weight: bold; font-size: 2em; text-align: center; padding:12px 0 0 0 !important; } .accordion p{padding:8px 0 8px 0 !important; margin:0 !important; overflow:auto;} .accordion > h3.opened {color: #333;} .accordion > h3.opened::before {content: '-'; line-height: 110%; background: #80cc26;} .accordion > div {height: 0; overflow: hidden;}
关键改动说明
- 核心逻辑优化:在点击事件开头增加了对当前h3展开状态的判断,已展开的项直接执行关闭操作并终止后续代码,彻底解决了「关闭后立刻重新展开」的问题。
- 选择器效率提升:把原代码中遍历所有h3判断class的逻辑,改成直接选择
.accordion > h3.opened,代码更简洁高效。 - HTML结构修正:移除了无效的h3嵌套结构,改成h3内部嵌套h4,符合HTML规范,避免浏览器自动修正结构导致的异常。
现在点击已展开的h3(显示减号)可以直接关闭手风琴,同时保留了原有的折叠动画效果,点击其他h3也能正常切换展开状态。
内容的提问来源于stack exchange,提问作者zuyi
相关产品推荐
相关产品推荐

