skip to Main Content

What I want to achieve:

I am making a list where I want each item to be collapsible, but I want to hide all of the other list elements when one is collapsed.

When one list item <div> is "collapsed" and showing, I want to toggle the display of the collapsible to be none and be able to "uncollapse or return to the original collapsible" by a click on the collapsed <div>.

enter image description here

What I have so far:

var coll = document.getElementsByClassName("collapsecontent");
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.display === "block") {
      content.style.display = "none";
    } else {
      content.style.display = "block";
    }
  });
}
button.collapsecontent {
  display: block;
  background-color: orange;
  border-color: blue;
  border-radius: 20px;
  width: 87.5%;
  margin-left: 6.2%;
  margin-top: 1%;
  transition: ease-out 10s;
  /*transition broken*/
  cursor: pointer;
}

div.content {
  display: none;
  background-color: orange;
  margin-left: 6.2%;
  margin-right: 6.2%;
  padding: 5%;
  border: 2px solid blue;
  border-radius: 20px;
  cursor: pointer;
}
<ul class="contentbox">
  <!--content boxes-->
  <button class="collapsecontent" type="button"><li class="contentbox"><h1>Works</h1></li></button>
  <div class="content">
    <p>Example</p>
  </div>


  <button class="collapsecontent" type="button"><li class="contentbox"><h1>Other</h1></li></button>
  <div class="content">
    <p>Example2</p>
  </div>


  <button class="collapsecontent" type="button"><li class="contentbox"><h1>About</h1></li></button>
  <div class="content">
    <p>Example3</p>
  </div>


  <button class="collapsecontent" type="button"><li class="contentbox"><h1>Placeholder</h1></li></button>
  <div class="content">
    <p>Example4</p>
  </div>

</ul>

I am also willing to explore ways other than collapsibles if it achieves the same results, but this was the only way I could think of.

2

Answers


  1. you can hide all content divs except the one currently being clicked and then toggle the display of the clicked item’s content div.

    For each button in collapsecontent:
        Add click event listener:
            For each content div in the page:
                If content div is not the next sibling of the clicked button:
                    Set display of content div to "none" (collapse it)
    
            Toggle display of the content div next to the clicked button:
                If its display is "block":
                    Set display to "none"
                Else:
                    Set display to "block"
    
    Login or Signup to reply.
  2. I recommend using details disclosure elements to implement this. Even though your desired behaviour is not an exact match for the default behaviour of such elements, it’s pretty close, and the additional semantics should improve the accessibility of your page.

    document.querySelector('.d1').addEventListener('click', evt => {
      if (evt.target.nodeName.toLowerCase() == 'details')
        evt.target.removeAttribute('open')
    })
    body {
      font-family: sans-serif;
    }
    
    .d1 details {
      background-color: orange;
      border: 2px solid blue;
      border-radius: 20px;
      width: 80%;
      margin: 5px auto;
      padding: 0 1rem;
      cursor: pointer;
    }
    
    .d1:has(details[open]) details {
      display: none;    /* if any details element is open, hide all of them ... */
    }
    
    .d1:has(details[open]) details[open] {
      display: block;   /* ... except the one which is actually open */
      padding: 1rem;
    }
    
    .d1:has(details[open]) details[open] summary {
      display: none;    /* hide the summary for any open element */
    }
    
    .d1 summary::-webkit-details-marker {
      display: none;    /* hide arrow on webkit browsers */
    }
    
    .d1 summary {
      list-style: none; /* hide arrow on non-webkit browsers */
      text-align: center;  
      font-size: 1.3em;
      font-weight: bold;
      padding: 1rem 0;
    }
    
    hr {
      margin-top: 3rem;
      border: 0;
      border-top: 1px solid silver;
    }
    <div class="d1">
    
      <details>
        <summary>Works</summary>
        Example1
      </details>
    
      <details>
        <summary>Other</summary>
        Example2
      </details>
    
      <details>
        <summary>About</summary>
        Example3
      </details>
    
      <details>
        <summary>Placeholder</summary>
        Example4
      </details>
    
    </div>
    
    <hr>
    
    <h4>Unstyled details disclosure elements for comparison</h4>
    
      <details>
        <summary>Works</summary>
        Example1
      </details>
    
      <details>
        <summary>Other</summary>
        Example2
      </details>
    
      <details>
        <summary>About</summary>
        Example3
      </details>
    
      <details>
        <summary>Placeholder</summary>
        Example4
      </details>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search