0

I have a ul and on click of one of its li I want to hide sub ul in it with sliding effect. I have tried animation with height from 100% to 0. But this is not working.

This is code snippet and in real scenario there will be dynamic data and n no of li

function hide() {
  var li = document.getElementById("game");
  game.classList.add("hide")
}
.hide {
  height: 0;
  overflow: hidden;
  animation-name: example;
  animation-duration: 4s;
}

@keyframes example {
  0% {
    height: 100%;
  }
  25% {
    height: 75%;
  }
  50% {
    height: 50%;
  }
  100% {
    height: 0%;
  }
}
<ul>
  <li>A</li>
  <li onclick="hide()">b</li>
  <li id="game" style="height:100%">
    <ul>
      <li>1</li>
      <li>2</li>
    </ul>
  </li>

</ul>

How can I achieve this?

Sunil Garg
  • 14,608
  • 25
  • 132
  • 189

1 Answers1

1

Using percentages will not work in your example.

Solution 1: You need to set a fixed height in the @keyframes like so:

function hide() {
  var li = document.getElementById("game");
  game.classList.add("hide")
}
.hide {
  height: 0;
  overflow: hidden;
  animation-name: example;
  animation-duration: 1s;
}

@keyframes example {
  0% {
    height: 40px;
  }
  25% {
    height: 30px;
  }
  50% {
    height: 20px;
  }
  100% {
    height: 0px;
  }
}
<ul>
  <li>A</li>
  <li onclick="hide()">b</li>
  <li id="game">
    <ul>
      <li>1</li>
      <li>2</li>
    </ul>
  </li>

</ul>

Solution 2: Add a fixed height to the parent <ul> element and then you can use percentages in your @keyframes like so:

function hide() {
  var li = document.getElementById("game");
  game.classList.add("hide")
}
.hide {
  height: 0;
  overflow: hidden;
  animation-name: example;
  animation-duration: 1s;
}

ul {
  height: 200px;
}

@keyframes example {
  0% {
    height: 100%;
  }
  25% {
    height: 75%;
  }
  50% {
    height: 50%;
  }
  100% {
    height: 0%;
  }
}
<ul>
  <li>A</li>
  <li onclick="hide()">b</li>
  <li id="game">
    <ul>
      <li>1</li>
      <li>2</li>
    </ul>
  </li>

</ul>

Here is an article that goes into detail on this subject.

R.F. Nelson
  • 2,254
  • 2
  • 12
  • 24
  • this works but in real scenario data is binding dynamically so there could be n no if li, so how can I identify what px i should start from ? – Sunil Garg May 29 '18 at 10:29
  • @SunilGarg Ah, that's a good point. You should edit your question to include that this data is dynamic. In that case, if you give the parent `
      ` element a fixed height then you can use percentages. The reason percentages aren't working in your example is because there is no element with a fixed height so when you add a percentage, the renderer is like "50% of what?! Nothing has a fixed height so I'm supposed to render this element 50% height of what?!" I added a solution where you can use percentages if you set a fixed height on the parent. You can also look into using `vh` units.
    – R.F. Nelson May 29 '18 at 10:33
  • Can't I give height in %, because I dont know the no of li so I dont know intial height in px? and I have updated the question – Sunil Garg May 29 '18 at 10:39
  • @SunilGarg I updated my answer. You will need a fixed height somewhere, so perhaps you could set the height of the `
      ` to a hard-coded value of `vh` units if it needs to be responsive. If this helped, please mark my answer as accepted. Thank you and best of luck.
    – R.F. Nelson May 29 '18 at 10:42
  • @SunilGarg Ultimately you may have to use JavaScript to dynamically adjust the height of the `
      ` element. For example, if there are `x` number of `
    • ` elements and you know you need `20px` for each of them, then you can use JavaScript to set the height of the `
        ` to `x * 20px`.
    – R.F. Nelson May 29 '18 at 10:44