Home > Mobile >  Why is my HTML/CSS collapsible not working?
Why is my HTML/CSS collapsible not working?

Time:11-02

Trying to create a collapsible segment on a webpage and so far have just tried the examples from W3 schools: https://www.w3schools.com/howto/howto_js_collapsible.asp. When I click the 'current' button the div does not become expanded.

I understand that the button tag needs to be directly next to the section to be collapsed, which I have. By playing around with the Inspect feature on my browser, it looks like the content.style.display setting is not being set properly on a click, as manually toggling it produces the desired effect. I looked at similar questions which suggested using this.parentNode.nextElementSibling instead of this.nextElementSibling, but this just produced the same behaviour. Does the location of the tag matter? Below is a snippet of the code - in essence just the code from the W3 website.

const coll = document.getElementsByClassName("collapsible");
let i;

for (i = 0; i < coll.length; i  ) {
   coll[i].addEventListener("click", function() {
        this.classList.toggle("active");
        let content = this.nextElementSibling;
        if (content.style.display === "block") {
                 content.style.display = "none";
        } else {
                 content.style.display = "block";
        }
  });
}
.collapsible {
      background-color: #eee;
      color: #444;
      cursor: pointer;
      padding: 18px;
      width: 100%;
      border: none;
      text-align: left;
      outline: none;
      font-size: 15px;
}
.content {
      padding: 0 18px;
      overflow: hidden;
      background-color: white;
      background-color: #f1f1f1;
}
.active, .collapsible:hover {
      background-color: #ccc;
}
<button type="button" >current</button>
<div >
        <p>Lorem ipsum...</p>
</div>

CodePudding user response:

The problem is in your JavaScript code.

It should be looking like this:

let coll = document.getElementsByClassName("collapsible");
              
for (let i = 0; i < coll.length; i  ) {
  coll[i].addEventListener("click", function() {
    this.classList.toggle("active");
    let content = this.nextElementSibling;
    if (content.style.maxHeight) {
      content.style.maxHeight = null;
    } else {
      content.style.maxHeight = content.scrollHeight   "px";
    }
  });
}

Your code should be looking like this (full version):

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .collapsible {
        background-color: #eee;
        color: #444;
        cursor: pointer;
        padding: 18px;
        width: 100%;
        border: none;
        text-align: left;
        outline: none;
        font-size: 15px;
      }
      .content {
        padding: 0 18px;
        overflow: hidden;
        background-color: white;
        max-height: 0;
        background-color: #f1f1f1;
        transition: max-height 0.2s ease-out;
      }
      .active,
      .collapsible:hover {
        background-color: #ccc;
      }
    </style>
  </head>
  <body>
    <button type="button" >current</button>
    <div >
      <p>Lorem ipsum...</p>
    </div>
    <script>
      let coll = document.getElementsByClassName("collapsible");

      for (let i = 0; i < coll.length; i  ) {
        coll[i].addEventListener("click", function () {
          this.classList.toggle("active");
          let content = this.nextElementSibling;
          if (content.style.maxHeight) {
            content.style.maxHeight = null;
          } else {
            content.style.maxHeight = content.scrollHeight   "px";
          }
        });
      }
    </script>
  </body>
</html>

Also, there's a way of using and achieving what you want by setting CSS property display, but in that case you have to remove property inside of CSS called overflow (basically delete it) -> it's placed inside of .content, here's full code of it:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .collapsible {
        background-color: #eee;
        color: #444;
        cursor: pointer;
        padding: 18px;
        width: 100%;
        border: none;
        text-align: left;
        outline: none;
        font-size: 15px;
      }
      .content {
        padding: 0 18px;
        background-color: white;
        max-height: 0;
        background-color: #f1f1f1;
        display:none;
        transition: max-height 0.2s ease-out;
      }
      .active,
      .collapsible:hover {
        background-color: #ccc;
      }
    </style>
  </head>
  <body>
    <button type="button" >current</button>
    <div >
      <p>Lorem ipsum...</p>
    </div>
    <script>
        let coll = document.getElementsByClassName("collapsible");

        for (let i = 0; i < coll.length; i  ) {
          coll[i].addEventListener("click", function() {
            this.classList.toggle("active");
            let content = document.getElementsByClassName("content")[0];
            if (content.style.display === "block") {
               content.style.display = "none";
            } else {
               content.style.display = "block";
            }
          });
        }
    </script>
  </body>
</html>

CodePudding user response:

1- put your script out of the body.

2- After I did that, there is still another problem. An extra click at the beginning. why are you using all this script? if it's only one element, then you don't need a loop. let me know if it's only one and I'll update the answer with a less and better script.

Anyway, I fixed it in your script by checking if display != none.

3- If you want some smooth animation, then you should use height instead of display then set the transition to 1s.

<body>
       <style>
        .collapsible {
                background-color: #eee;
                color: #444;
                cursor: pointer;
                padding: 18px;
                width: 100%;
                border: none;
                text-align: left;
                outline: none;
                font-size: 15px;
                border: 1px solid;
                }

        .content {
                padding: 0 18px;
                display: block;
                overflow: hidden;
                background-color: white;
                background-color: #f1f1f1;
                border: 1px solid red;
                }

        .active, .collapsible:hover {
                background-color: #ccc;
                }
        </style>
       
        <button type="button" >current</button>
        <div >
                <p>Lorem ipsum...</p>
        </div>

</body>

<script>
    
      const coll = document.getElementsByClassName("collapsible");

    for (i = 0; i < coll.length; i  ) {
       coll[i].addEventListener("click", function() {
            this.classList.toggle("active");
            let content = this.nextElementSibling;
            if (content.style.display != "none") {
                     content.style.display = "none";
            } else {
                     content.style.display = "block";
            }
      });
    }
    
</script>


Edit: regarding your comment:

for that then just use this one from w3schools, it works fine for me.

<style>
        .collapsible {
          background-color: #777;
          color: white;
          cursor: pointer;
          padding: 18px;
          width: 100%;
          border: none;
          text-align: left;
          outline: none;
          font-size: 15px;
        }
        
        .active, .collapsible:hover {
          background-color: #555;
        }
        
        .content {
          padding: 0 18px;
          max-height: 0;
          overflow: hidden;
          transition: max-height 0.2s ease-out;
          background-color: #f1f1f1;
        }
        </style>
        </head>
        <body>
        
        <h2>Animated Collapsibles</h2>
        
        <p>A Collapsible:</p>
        <button >Open Collapsible</button>
        <div >
          <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>
        
        <p>Collapsible Set:</p>
        <button >Open Section 1</button>
        <div >
          <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 >Open Section 2</button>
        <div >
          <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 >Open Section 3</button>
        <div >
          <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 coll = document.getElementsByClassName("collapsible");
        var i;
        
        for (i = 0; i < coll.length; i  ) {
          coll[i].addEventListener("click", function() {
            this.classList.toggle("active");
            var content = this.nextElementSibling;
            if (content.style.maxHeight){
              content.style.maxHeight = null;
            } else {
              content.style.maxHeight = content.scrollHeight   "px";
            } 
          });
        }
        </script>

  • Related