手风琴默认展开项点击无法关闭的问题排查
手风琴默认展开项点击无法关闭的问题解决
问题出在CSS类控制的初始展开状态和JS的行内样式判断逻辑不匹配:
- 你通过给按钮加
.open类,用CSS选择器.open + .content-wrapper设置max-height: none实现默认展开,但JS里判断展开状态时,只检查content-wrapper的行内style.maxHeight,而初始状态下这个行内属性是不存在的。 - 点击已展开的按钮时,流程冲突:
- JS先移除其他按钮的
.open类并重置它们的行内maxHeight - 执行
this.classList.toggle("open"),当前按钮的.open类被移除,CSS控制的max-height: none失效,内容本该收起 - 但JS判断
nextAccordionButton.style.maxHeight为空,会再次给它设置行内maxHeight: scrollHeight,导致内容重新展开,视觉上看起来按钮没关闭反而重复展开
- JS先移除其他按钮的
解决方法(二选一即可)
方法1:修改JS状态判断逻辑,结合按钮的.open类
直接通过按钮的类判断展开状态,避免CSS和JS的状态错位:
function switchClasses() { // 关闭其他所有手风琴项 for (var i = 0; i < accordionButton.length; i++) { if (this !== accordionButton[i]) { accordionButton[i].classList.remove("open"); accordionButton[i].nextElementSibling.style.maxHeight = null; } } // 提前判断当前项是否处于展开状态 const isOpen = this.classList.contains("open"); this.classList.toggle("open"); var contentWrapper = this.nextElementSibling; if (isOpen) { contentWrapper.style.maxHeight = null; } else { contentWrapper.style.maxHeight = contentWrapper.scrollHeight + "px"; } }
方法2:用JS初始化默认展开状态(替代CSS类的方式)
移除HTML中按钮的.open类,改用JS在页面加载时主动设置展开状态,确保CSS和JS状态统一:
var accordionButton = document.querySelectorAll("button"); // 初始化展开第一个项 const firstButton = accordionButton[0]; const firstContent = firstButton.nextElementSibling; firstButton.classList.add("open"); firstContent.style.maxHeight = firstContent.scrollHeight + "px"; for (var i = 0; i < accordionButton.length; i++) { accordionButton[i].addEventListener("click", switchClasses); } function switchClasses() { for (var i = 0; i < accordionButton.length; i++) { if (this !== accordionButton[i]) { accordionButton[i].classList.remove("open"); accordionButton[i].nextElementSibling.style.maxHeight = null; } } this.classList.toggle("open"); var contentWrapper = this.nextElementSibling; if (contentWrapper.style.maxHeight) { contentWrapper.style.maxHeight = null; } else { contentWrapper.style.maxHeight = contentWrapper.scrollHeight + "px"; } }
修正后的完整代码(以方法1为例)
HTML
<div class="accordion-item"> <button class="open"> <span class="accordion__title">Accordion 1</span> </button> <div class="content-wrapper"> <div class="content"> <p>Accordion 1 content.</p> </div> </div> </div> <div class="accordion-item"> <button> <span class="accordion__title">Accordion 2</span> </button> <div class="content-wrapper"> <div class="content"> <p>Accordion 2 content.</p> </div> </div> </div> <div class="accordion-item"> <button> <span class="accordion__title">Accordion 3</span> </button> <div class="content-wrapper"> <div class="content"> <p>Accordion 3 content.</p> </div> </div> </div>
CSS
.accordion-item { border: 1px solid lightgrey; } button { background: none; border: none; width: 100%; max-width: none; height: auto; padding: 12px; text-align: left; cursor: pointer; transition: 0.5s; } .content-wrapper { max-height: 0; overflow: hidden; transition: max-height 0.2s ease-out; } .content { padding: 0 10px; } .open { background: lightgray; border-bottom: none; } .open + .content-wrapper { max-height: none; }
JavaScript
var accordionButton = document.querySelectorAll("button"); for (var i = 0; i < accordionButton.length; i++) { accordionButton[i].addEventListener("click", switchClasses); } function switchClasses() { for (var i = 0; i < accordionButton.length; i++) { if (this !== accordionButton[i]) { accordionButton[i].classList.remove("open"); accordionButton[i].nextElementSibling.style.maxHeight = null; } } const isOpen = this.classList.contains("open"); this.classList.toggle("open"); var contentWrapper = this.nextElementSibling; if (isOpen) { contentWrapper.style.maxHeight = null; } else { contentWrapper.style.maxHeight = contentWrapper.scrollHeight + "px"; } }
内容的提问来源于stack exchange,提问作者Nesta
相关产品推荐
相关产品推荐

