skip to Main Content

I have an sidenav with accordion menus, but when I refresh or go to another page it closes. How can it be stay open after these actions? Example here with CSS: https://jsfiddle.net/ag9q1tvc/

JavaScript:

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

for (i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var parent = this.parentElement;
    var panel = this.nextElementSibling;
    if (panel.style.maxHeight){
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
      parent.style.maxHeight = parseInt(parent.style.maxHeight) + panel.scrollHeight + "px";
    } 
  });
}

HTML:

<div class='sidenav'>
  <button class='accordion'><i class='fa fa-star' aria-hidden='true'></i>&nbsp; FAV</button>
  <button class='accordion'><i class='fa fa-th-large' aria-hidden='true'></i>&nbsp; SALES</button>
  <div class='panel'>
      <a href='item1.php'>&emsp;ITEM 1</a>
       <a href='item2.php'>&emsp;ITEM 2</a>
</div>

I couldn’t find the exact method for my problem in other answers.
Thank you!

3

Answers


  1. You can try to use local storage, it is a variable that is store in the cache of the browser

    localStorage.setItem("item1", "active");
    

    You can see more info here.

    Login or Signup to reply.
  2. You need to store accordion state somewhere, it can be sessionStorage or localStorage also called cookies. As for me sessionStorage is the best way of doing that, here is an example of what you can do:

    for (i = 0; i < acc.length; i++) {
      acc[i].addEventListener("click", function() {
        this.classList.toggle("active");
        var parent = this.parentElement;
        var panel = this.nextElementSibling;
        if (panel.style.maxHeight) {
          panel.style.maxHeight = null;
          sessionStorage.setItem(parent.id, ""); // store it as closed
        } else {
          panel.style.maxHeight = panel.scrollHeight + "px";
          parent.style.maxHeight = parseInt(parent.style.maxHeight) + panel.scrollHeight + "px";
          sessionStorage.setItem(parent.id, "open"); // store it as open
        }
      });
    
      // here we are getting state from sessionStorage
      var parent = acc[i].parentElement;
      if (sessionStorage.getItem(parent.id) === "open") {
        parent.querySelector(".panel").style.maxHeight = parent.querySelector(".panel").scrollHeight + "px";
        parent.style.maxHeight = parseInt(parent.style.maxHeight) + parent.querySelector(".panel").scrollHeight + "px";
        acc[i].classList.add("active");
      }
    }
    

    Note that it will store state until browser is closed, otherwise you can use cookies.

    Login or Signup to reply.
  3. :target Selector and anchor tag (no JS)

    The :target selector matches if the id of an element is equal to the hash (#) after the url. Since the browser keeps the hash with reload or navigation, this will persist the state of the accordion in the url.

    • PRO: No JavaScript needed, cross-browser compatible
    • CON: If you need the # for something else (like single page routing) this is not an option.
    #accordion {
      display: blocK;
      border: 2px solid blue;
    }
    
    #accordion > .content {
      display: none;
    }
    
    #accordion:target > .content {
      display: block;
    }
    <a href="#accordion">open</a>
    <a href="#">close</a>
    
    <a id="accordion">
      <div class="content">
        Content
      </div>
    </a>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search