【问题标题】:How to close accordion panels when another one opens?当另一个手风琴面板打开时如何关闭手风琴面板?
【发布时间】:2019-03-26 18:21:30
【问题描述】:

我的静态 HTML/CSS/JS 网站上有手风琴小部件。

默认情况下所有手风琴都是关闭的。

用户可以打开其中任何一个,并且这些将保持打开状态,直到用户通过单击手风琴标题手动关闭它们。

当用户点击打开另一个手风琴时,如何关闭以前打开的手风琴?

我使用这个模板创建了我的手风琴:https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_accordion_animate

我把 HTML 和 JS 都放在了 HTML 文件中:

var acc = document.getElementsByClassName("accordion");
var i;

for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight){
  panel.style.maxHeight = null;
} else {
  panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
.accordion {
  color: #fff;
  background-color: #00000042;
  cursor: pointer;
  padding: 10px 10px;
  margin-top:20px;
  width: 100%;
  border: 1px solid #00000042;
  text-align: left;
  outline: none;
  transition: 0.4s;
}

.active, .accordion:hover {
  background-color: #00000042;
  border: 1px solid #fc8e2d;
}

.panel {
  padding: 0 18px;
  font-size: 18px;
  background-color: #00000042;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease-out;
}
<button class="accordion"><span class="faq__question-heading">Title1</span></button>
<div class="panel">
  <p style="padding:18px 0;">description1</p>
</div>

<button class="accordion"><span class="faq__question-heading">Title2</span></button>
<div class="panel">
  <p style="padding:18px 0;">description2</p>
</div>

<button class="accordion"><span class="faq__question-heading">Title3</span></button>
<div class="panel">
  <p style="padding:18px 0;">description3</p>
</div>

<script>

</script>

【问题讨论】:

    标签: javascript html css


    【解决方案1】:

    在我完成代码时已经给出了一些答案;)。但是无论如何我都会做出贡献。每次打开手风琴时,您都必须执行一些额外的代码。您必须获得具有 .active 类的元素 - 在您的情况下,我们将使用 .accordion.active。之后,有必要从找到的元素中删除 .active 类。最后,您必须更新以下面板的max-height。您可以使用nextElementSilbling 执行此操作。这是更新后的 JS 代码:

      let active = document.querySelectorAll(".accordion-div .accordion.active");
      for(let j = 0; j < active.length; j++){
        active[j].classList.remove("active");
        active[j].nextElementSibling.style.maxHeight = null; //or 0px
      }
    

    此外,我更新了 HTML 以更好地封装组件。我将&lt;div&gt; 包裹在所有内容周围,以便更好地应用选择器来检索元素。希望这可以帮助。我复制了您的答案并对其进行了更新以生成一个工作示例。如果您想在每页使用多个手风琴,我建议您使用id= 来检索正确的手风琴。否则所有的手风琴都会关闭,这不应该是故意发生的。

    var acc = document.getElementsByClassName("accordion");
    var i;
    
    for (i = 0; i < acc.length; i++) {
    acc[i].addEventListener("click", function() {
    
    var panel = this.nextElementSibling;
    if (panel.style.maxHeight){
      panel.style.maxHeight = null;
    } else {
      let active = document.querySelectorAll(".accordion-div .accordion.active");
      for(let j = 0; j < active.length; j++){
        active[j].classList.remove("active");
        active[j].nextElementSibling.style.maxHeight = null;
      }
      this.classList.toggle("active");
      panel.style.maxHeight = panel.scrollHeight + "px";
    }
    });
    }
    .accordion {
      color: #fff;
      background-color: #00000042;
      cursor: pointer;
      padding: 10px 10px;
      margin-top:20px;
      width: 100%;
      border: 1px solid #00000042;
      text-align: left;
      outline: none;
      transition: 0.4s;
    }
    
    .active, .accordion:hover {
      background-color: #00000042;
      border: 1px solid #fc8e2d;
    }
    
    .panel {
      padding: 0 18px;
      font-size: 18px;
      background-color: #00000042;
      max-height: 0;
      overflow: hidden;
      transition: max-height 0.3s ease-out;
    }
    <div class="accordion-div">
      <button class="accordion"><span class="faq__question-heading">Title1</span></button>
      <div class="panel">
        <p style="padding:18px 0;">description1</p>
      </div>
    
      <button class="accordion"><span class="faq__question-heading">Title2</span></button>
      <div class="panel">
        <p style="padding:18px 0;">description2</p>
      </div>
    
      <button class="accordion"><span class="faq__question-heading">Title3</span></button>
      <div class="panel">
        <p style="padding:18px 0;">description3</p>
      </div>
    </div>

    【讨论】:

    • 非常感谢 Thex!这个完美!我已经将它应用到我的网站上。以前打开的手风琴现在在用户单击打开一个新的手风琴时关闭,并且用户仍然可以通过单击其标题来关闭手风琴。伟大的!再次感谢!
    • @Borisa 不客气,但请注意,我多次更新了我的答案以使其更流畅,并且故意在某个时间点添加了一个错误。所以请检查您是否有最新答案的代码。现在一直这样!
    【解决方案2】:

    您可以在单击事件处理程序中再使用一个 for 循环来重置高度。如果手风琴打开,它也会关闭。

    for (var j = 0; j < acc.length; j++) {
        acc[j].nextElementSibling.style.maxHeight = null;
    }
    

    请看下面的片段:

    var acc = document.getElementsByClassName("accordion");
    
    for (let i = 0; i < acc.length; i++) {
      acc[i].addEventListener("click", function() {
        for (let j = 0; j < acc.length; j++) {
        acc[j].classList.remove("active");
          if(j!=i){
            acc[j].nextElementSibling.style.maxHeight = null;
          }
        }
        this.classList.add("active");
        var panel = this.nextElementSibling;
        if (panel.style.maxHeight){
          panel.style.maxHeight = null;
        } else {
          panel.style.maxHeight = panel.scrollHeight + "px";
        }
      });
    }
    .accordion {
      color: #fff;
      background-color: #00000042;
      cursor: pointer;
      padding: 10px 10px;
      margin-top:20px;
      width: 100%;
      border: 1px solid #00000042;
      text-align: left;
      outline: none;
      transition: 0.4s;
    }
    
    .active, .accordion:hover {
      background-color: #00000042;
      border: 1px solid #fc8e2d;
    }
    
    .panel {
      padding: 0 18px;
      font-size: 18px;
      background-color: #00000042;
      max-height: 0;
      overflow: hidden;
      transition: max-height 0.3s ease-out;
    }
    <button class="accordion"><span class="faq__question-heading">Title1</span></button>
    <div class="panel">
      <p style="padding:18px 0;">description1</p>
    </div>
    
    <button class="accordion"><span class="faq__question-heading">Title2</span></button>
    <div class="panel">
      <p style="padding:18px 0;">description2</p>
    </div>
    
    <button class="accordion"><span class="faq__question-heading">Title3</span></button>
    <div class="panel">
      <p style="padding:18px 0;">description3</p>
    </div>
    
    <script>
    
    </script>

    【讨论】:

    • 非常感谢尼米特!我感谢您的帮助!我尝试了您的解决方案,它关闭了以前打开的手风琴,就像我想要的那样,但是通过单击其标题来关闭手风琴的选项不再起作用。这两种东西可以兼得吗?
    【解决方案3】:

    只需将&lt;script&gt; 中的其他maxHeight 属性重置为空,如下所示:

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <style>
        .accordion {
          background-color: #eee;
          color: #444;
          cursor: pointer;
          padding: 18px;
          width: 100%;
          border: none;
          text-align: left;
          outline: none;
          font-size: 15px;
          transition: 0.4s;
        }
        
        .active,
        .accordion:hover {
          background-color: #ccc;
        }
        
        .panel {
          padding: 0 18px;
          background-color: white;
          max-height: 0;
          overflow: hidden;
          transition: max-height 0.2s ease-out;
        }
      </style>
    </head>
    
    <body>
    
      <h2>Animated Accordion</h2>
      <p>Click on the buttons to open the collapsible content.</p>
    
      <button class="accordion">Section 1</button>
      <div class="panel">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
      </div>
    
      <button class="accordion">Section 2</button>
      <div class="panel">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
      </div>
    
      <button class="accordion">Section 3</button>
      <div class="panel">
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
      </div>
    
      <script>
        var acc = document.getElementsByClassName("accordion");
    
        for (let i = 0; i < acc.length; i++) {
          acc[i].addEventListener("click", function() {
            this.classList.toggle("active");
            for (j = 0; j < acc.length; j++) {
              if (j !== i)
                acc[j].nextElementSibling.style.maxHeight = null;
            }
            var panel = this.nextElementSibling;
            if (panel.style.maxHeight) {
              panel.style.maxHeight = null;
            } else {
              panel.style.maxHeight = panel.scrollHeight + "px";
            }
          });
        }
      </script>
    
    </body>
    
    </html>

    【讨论】:

    • 非常感谢暗里!我感谢您的帮助!我尝试了您的解决方案,它关闭了以前打开的手风琴,就像我想要的那样,但是通过单击其标题来关闭手风琴的选项不再起作用。这两种东西可以兼得吗?
    • @Borisa 是的,我更新了,只需要在循环内定义i
    【解决方案4】:
    var acc = document.getElementsByClassName("accordion");
    var i;
    
    for (i = 0; i < acc.length; i++) {
    acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    
    // init: close all accordions
    var allAcc = document.getElementsByClassName("accordion");
    for (var e = 0; e < allAcc.length; e++) {
      var aPanel = allAcc[e].nextElementSibling;
      aPanel.style.maxHeight = null;
    }
    
    var panel = this.nextElementSibling;
    if (panel.style.maxHeight){
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    }
    });
    }
    

    编辑: 我在注释“// init:关闭所有手风琴”之后添加了 5 行。 正如评论所说,这些行关闭了所有手风琴。这是通过获取所有具有“手风琴”类的元素来完成的。通过循环遍历这些元素,使用包含手风琴描述的面板 div(手风琴元素的下一个兄弟元素)。此面板元素的高度设置为“null” - 因此它没有高度(类似于“invisible”或“display:none”)。 我使用了这个代码,因为它也用于询问者的代码中,以在有人单击手风琴时关闭面板。

    【讨论】:

    • 好的,我添加了描述。
    猜你喜欢
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多