Reinier68
Reinier68

Reputation: 3242

Why is my Accordion closing animation not firing? It opens (with animation) but closes without animation

Here is a Fiddle of my problem (Click the image next to the 'Werknemers' or 'Verzuimdossiers').

I got a sidebar in which some items have subcontent and some don't. So I made an accordion with subnav items. The problem is that the opening animation works fine. However, the closing animation is not being fired.

What could be the issue here?

Code for reference

openSubnav = (evt, subNavName) => {
  let i, subnavContent, subnavLinks;

  //Check if the current accordion is clicked again to close it.
  const subNav = document.getElementById(subNavName)
  if (getComputedStyle(subNav).display === 'block') {
    subNav.style.display = 'none'
    evt.currentTarget.className = evt.currentTarget.className.replace(" subnav-isActive", "");
    subNav.style.maxHeight = null;
    return
  }
  //hide alle subnav content
  subnavContent = document.getElementsByClassName("subnav-content");
  for (i = 0; i < subnavContent.length; i++) {
    subnavContent[i].style.display = "none";

  }
  //delete the subnav-isActive class
  subnavLinks = document.getElementsByClassName("subnav-item");
  for (i = 0; i < subnavLinks.length; i++) {
    subnavLinks[i].className = subnavLinks[i].className.replace(" subnav-isActive", "");
  }
  //Display the content
  subNav.style.display = "block";
  //Add the subnav-isActive class
  evt.currentTarget.className += " subnav-isActive";

  //If there currently is a max-height on the element, delete it.
  if (subNav.style.maxHeight) {
    subNav.style.maxHeight = null;
  }
  subNav.style.maxHeight = subNav.scrollHeight + "px";
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.root {
  display: flex;
  font-family: 'Poppins', sans-serif;
}

nav {
  -webkit-user-select:none;
  -moz-user-select:none;
  -ms-user-select:none;
  -o-user-select:none;
  user-select:none;
}

.icon-container {
  width: 60px; 
  height: 50px; 
  display: flex; 
  justify-content: center; 
  align-items: center;
}

/* .sidebar:hover {
  width: 250px;
  overflow: visible;
} */

.sidebar {
  width: 250px;
}

.sidebar {
  background-color: #8dc4d9;
  position:absolute;
  top:0;
  bottom:0;
  height:100%;
  left:0;
  /* width:60px; */
  overflow:hidden;
  -webkit-transition:width .05s linear;
  transition:width .05s linear;
}

.sidebar>ul {
  margin: 10px 0;
}

.sidebar li {
  width:250px;
}

.sidebar li>span {
  position: relative;
  display: table;
  border-collapse: collapse;
  border-spacing: 0;
  font-size: 14px;
  transition: all .1s linear;
}

.sidebar .nav-text {
  display: table-cell;
  vertical-align: middle;
  /* 250px breed totaal - 60px breed icoon = 190 */
  width: 190px;
}

.sidebar .nav-dropdown {
  display: table-cell;
  vertical-align: middle;
  cursor: pointer;
  padding-right: 20px;
  padding-top: 8px;
}

.sidebar .nav-dropdown img {
  transform: rotate(270deg);
  transition: transform .3s ease;
}

.sidebar .nav-dropdown.subnav-isActive img {
  transform: rotate(360deg);
}

.user {
  margin-bottom: 20px;
}

.sidebar li:hover>span {
  background-color:#76abbf;
}

.subnav-content {
  display: none;
  /* 17px omdat de afbeelding 24x24 is en de breedte van de sidebar 60px. 
     Met de afbeelding houd je dus 17px aan beiden kanten over. */
  padding: 10px 17px;
  background-color:#76abbf;
  list-style: none;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}

.content {
  width: calc(50% - 30px);
  background-color: #f3f6f9;
}

.preview {
  width: calc(50% - 30px);
  background-color: #f3f6f9;
}
<!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">
  <link rel="stylesheet" href="style.css">
  <script src="script.js"></script>
  <title>Sidebar</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet">
</head>

<body>
  <div class="root">
    <nav class="sidebar">
      <ul>
        <li class="user">
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/user32.png" alt="">
            </div>
            <span class="nav-text">
              Mijn account
            </span>
          </span>
        </li>
        <li>
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/bureaublad24.png" alt="">
            </div>
            <span class="nav-text">
              Dashboard
            </span>
          </span>
        </li>
        <li class="has-subnav">
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/werknemers24.png" alt="">
            </div>
            <span class="nav-text">
              Werknemers
            </span>
            <span class="nav-dropdown subnav-item" onclick="openSubnav(event, 'Werknemers')">
              <img src="./icons24/DropdownArrow16.png">
            </span>
          </span>
          <ul id="Werknemers" class="subnav-content">
            <li>kaas</li>
            <li>brood</li>
            <li>eieren</li>
          </ul>
        </li>
        <li>
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/verzuimdossiers24.png" alt="">
            </div>
            <span class="nav-text">
              Verzuimdossiers
            </span>
            <span class="nav-dropdown subnav-item" onclick="openSubnav(event, 'Verzuimdossiers')">
              <img src="./icons24/DropdownArrow16.png">
            </span>
          </span>
          <ul id="Verzuimdossiers" class="subnav-content">
            <li>boter</li>
            <li>friet</li>
            <li>pasta</li>
          </ul>
        </li>
        <li>
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/trajecten24.png" alt="">
            </div>
            <span class="nav-text">
              Trajecten
            </span>
          </span>
        </li>
        <li>
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/projecten24.png" alt="">
            </div>
            <span class="nav-text">
              Projecten
            </span>
          </span>
        </li>
      </ul>
    </nav>
    <div class="content">
      Content
    </div>
    <div class="preview">
      Preview
    </div>
  </div>
</body>

</html>

Upvotes: 0

Views: 451

Answers (2)

Vlastimil Lis&#225;k
Vlastimil Lis&#225;k

Reputation: 146

You need to set timeout before the display: none so it has time to prosecute the closing animation.

Like in this code:

  const subNav = document.getElementById(subNavName)
  if (getComputedStyle(subNav).display === 'block') {
    evt.currentTarget.className = evt.currentTarget.className.replace(" subnav-isActive", "");
    subNav.style.maxHeight = null;
    setTimeout(function(){subNav.style.display = 'none';}, 100);
    return
  }

Here you have the right code complete (idk why, but you need to expand the snippet to see it working, click on Run code snippet and then Full page link):

openSubnav = (evt, subNavName) => {
  let i, subnavContent, subnavLinks;

  //Check if the current accordion is clicked again to close it.
  const subNav = document.getElementById(subNavName)
  if (getComputedStyle(subNav).display === 'block') {
    evt.currentTarget.className = evt.currentTarget.className.replace(" subnav-isActive", "");
    subNav.style.maxHeight = null;
    setTimeout(function(){subNav.style.display = 'none';}, 100);
    return
  }
  //hide alle subnav content
  subnavContent = document.getElementsByClassName("subnav-content");
  for (i = 0; i < subnavContent.length; i++) {
    subnavContent[i].style.display = "none";

  }
  //delete the subnav-isActive class
  subnavLinks = document.getElementsByClassName("subnav-item");
  for (i = 0; i < subnavLinks.length; i++) {
    subnavLinks[i].className = subnavLinks[i].className.replace(" subnav-isActive", "");
  }
  //Display the content
  subNav.style.display = "block";
  //Add the subnav-isActive class
  evt.currentTarget.className += " subnav-isActive";

  //If there currently is a max-height on the element, delete it.
  if (subNav.style.maxHeight) {
    subNav.style.maxHeight = null;
  }
  subNav.style.maxHeight = subNav.scrollHeight + "px";
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.root {
  display: flex;
  font-family: 'Poppins', sans-serif;
}

nav {
  -webkit-user-select:none;
  -moz-user-select:none;
  -ms-user-select:none;
  -o-user-select:none;
  user-select:none;
}

.icon-container {
  width: 60px; 
  height: 50px; 
  display: flex; 
  justify-content: center; 
  align-items: center;
}

/* .sidebar:hover {
  width: 250px;
  overflow: visible;
} */

.sidebar {
  width: 250px;
}

.sidebar {
  background-color: #8dc4d9;
  position:absolute;
  top:0;
  bottom:0;
  height:100%;
  left:0;
  /* width:60px; */
  overflow:hidden;
  -webkit-transition:width .05s linear;
  transition:width .05s linear;
}

.sidebar>ul {
  margin: 10px 0;
}

.sidebar li {
  width:250px;
}

.sidebar li>span {
  position: relative;
  display: table;
  border-collapse: collapse;
  border-spacing: 0;
  font-size: 14px;
  transition: all .1s linear;
}

.sidebar .nav-text {
  display: table-cell;
  vertical-align: middle;
  /* 250px breed totaal - 60px breed icoon = 190 */
  width: 190px;
}

.sidebar .nav-dropdown {
  display: table-cell;
  vertical-align: middle;
  cursor: pointer;
  padding-right: 20px;
  padding-top: 8px;
}

.sidebar .nav-dropdown img {
  transform: rotate(270deg);
  transition: transform .3s ease;
}

.sidebar .nav-dropdown.subnav-isActive img {
  transform: rotate(360deg);
}

.user {
  margin-bottom: 20px;
}

.sidebar li:hover>span {
  background-color:#76abbf;
}

.subnav-content {
  display: none;
  /* 17px omdat de afbeelding 24x24 is en de breedte van de sidebar 60px. 
     Met de afbeelding houd je dus 17px aan beiden kanten over. */
  padding: 10px 17px;
  background-color:#76abbf;
  list-style: none;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}

.content {
  width: calc(50% - 30px);
  background-color: #f3f6f9;
}

.preview {
  width: calc(50% - 30px);
  background-color: #f3f6f9;
}
<!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">
  <link rel="stylesheet" href="style.css">
  <script src="script.js"></script>
  <title>Sidebar</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet">
</head>

<body>
  <div class="root">
    <nav class="sidebar">
      <ul>
        <li class="user">
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/user32.png" alt="">
            </div>
            <span class="nav-text">
              Mijn account
            </span>
          </span>
        </li>
        <li>
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/bureaublad24.png" alt="">
            </div>
            <span class="nav-text">
              Dashboard
            </span>
          </span>
        </li>
        <li class="has-subnav">
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/werknemers24.png" alt="">
            </div>
            <span class="nav-text">
              Werknemers
            </span>
            <span class="nav-dropdown subnav-item" onclick="openSubnav(event, 'Werknemers')">
              <img src="./icons24/DropdownArrow16.png">
            </span>
          </span>
          <ul id="Werknemers" class="subnav-content">
            <li>kaas</li>
            <li>brood</li>
            <li>eieren</li>
          </ul>
        </li>
        <li>
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/verzuimdossiers24.png" alt="">
            </div>
            <span class="nav-text">
              Verzuimdossiers
            </span>
            <span class="nav-dropdown subnav-item" onclick="openSubnav(event, 'Verzuimdossiers')">
              <img src="./icons24/DropdownArrow16.png">
            </span>
          </span>
          <ul id="Verzuimdossiers" class="subnav-content">
            <li>boter</li>
            <li>friet</li>
            <li>pasta</li>
          </ul>
        </li>
        <li>
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/trajecten24.png" alt="">
            </div>
            <span class="nav-text">
              Trajecten
            </span>
          </span>
        </li>
        <li>
          <span>
            <div class="icon-container">
              <img class="nav-icon" src="./icons24/projecten24.png" alt="">
            </div>
            <span class="nav-text">
              Projecten
            </span>
          </span>
        </li>
      </ul>
    </nav>
    <div class="content">
      Content
    </div>
    <div class="preview">
      Preview
    </div>
  </div>
</body>

</html>

Upvotes: 3

T.Trassoudaine
T.Trassoudaine

Reputation: 1365

The reason is because your animation takes some time to execute, but you assign display: none before your animation has any chance to be rendered.

Upvotes: 2

Related Questions