1

I'm trying to do scrollUp and scrollDown with a native JS Element.animate(). I want the element to appear smoothly from the top to the bottom. What I get is an immediate opening and delayed collapsing. If there are currently better ways to do it, I'd like to know, I'm still curious why doesn't this work though.

document.addEventListener('DOMContentLoaded', function() {
  document.getElementById('addNewScriptStep').onclick = function() {
    let list = document.getElementById('collapsibleActionList');
    let newHeight = '100%';
    if (list.dataset.iscollapsed == 'false') {
      newHeight = '0';
    }
    list.dataset.iscollapsed = !eval(list.dataset.iscollapsed);
    list.animate({
      height: newHeight
    }, {
      fill: 'forwards',
      duration: 500
    });
  };
});
#collapsibleActionList {
  overflow: hidden;
  height: 0;
  transition: height 0.5s;
}
<html>

<body>
  <a href="javascript:void(0)" id="addNewScriptStep" class=""> Add an action </a>
  <ul id="collapsibleActionList" data-iscollapsed="true">
    <li data-type="open_url">Open URL</li>
    <li data-type="href_to">Click link</li>
    <li data-type="click_element">Click element</li>
    <li data-type="insert_into">Insert into textbox</li>
    <li data-type="sleep">Sleep</li>
    <li data-type="checked">Check checkbox</li>
    <li data-type="unchecked">Uncheck checkbox</li>
    <li data-type="send_form">Submit form</li>
    <li data-type="if_element_is_defined">Continue if HTML contains element</li>
    <li data-type="if_element_is_not_defined">Continue if HTML doesn't contain element</li>
    <li data-type="if_text_is_defined">Continue if there is text</li>
    <li data-type="if_text_is_not_defined">Continue if there is no text</li>
  </ul>
</body>

</html>

Edit: I noticed that after removing CSS transition property, the list can no longer collapse, though animate function IS being called with {height: '0'}

horart
  • 33
  • 1
  • 4
  • Does this answer your question? [How can I transition height: 0; to height: auto; using CSS?](https://stackoverflow.com/questions/3508605/how-can-i-transition-height-0-to-height-auto-using-css) – Yogi Apr 22 '22 at 11:41
  • @Yogi, thanks for the link. Sadly, after changing height to max-height and 100% to 1000px I didn't get any results, now it just doesn't even open, no matter what transition is – horart Apr 22 '22 at 12:01

2 Answers2

0

with useing max-height instead of height you can do it.

document.addEventListener('DOMContentLoaded', function() {
  document.getElementById('addNewScriptStep').onclick = function() {
    let list = document.getElementById('collapsibleActionList');
    let newHeight = '999px';
    if (list.dataset.iscollapsed == 'false') {
      newHeight = '0';
    }
    list.dataset.iscollapsed = !eval(list.dataset.iscollapsed);
    list.animate({
      maxHeight: newHeight
    }, {
      fill: 'forwards',
      duration: 500
    });
  };
});
#collapsibleActionList {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.5s;
}
<body>
  <a href="javascript:void(0)" id="addNewScriptStep" class=""> Add an action </a>
  <ul id="collapsibleActionList" data-iscollapsed="true">
    <li data-type="open_url">Open URL</li>
    <li data-type="href_to">Click link</li>
    <li data-type="click_element">Click element</li>
    <li data-type="insert_into">Insert into textbox</li>
    <li data-type="sleep">Sleep</li>
    <li data-type="checked">Check checkbox</li>
    <li data-type="unchecked">Uncheck checkbox</li>
    <li data-type="send_form">Submit form</li>
    <li data-type="if_element_is_defined">Continue if HTML contains element</li>
    <li data-type="if_element_is_not_defined">Continue if HTML doesn't contain element</li>
    <li data-type="if_text_is_defined">Continue if there is text</li>
    <li data-type="if_text_is_not_defined">Continue if there is no text</li>
  </ul>
</body>

you can do this in a simpler way. if you want?

const link = document.getElementById('addNewScriptStep')
const list = document.getElementById('collapsibleActionList')
link.addEventListener('click',()=>{
  list.classList.toggle('open')
})
#collapsibleActionList {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.5s;
}
#collapsibleActionList.open {
  overflow: hidden;
  max-height: 999px;
  transition: max-height 0.5s;
}
<body>
  <a href="javascript:void(0)" id="addNewScriptStep" class=""> Add an action </a>
  <ul id="collapsibleActionList" data-iscollapsed="true">
    <li data-type="open_url">Open URL</li>
    <li data-type="href_to">Click link</li>
    <li data-type="click_element">Click element</li>
    <li data-type="insert_into">Insert into textbox</li>
    <li data-type="sleep">Sleep</li>
    <li data-type="checked">Check checkbox</li>
    <li data-type="unchecked">Uncheck checkbox</li>
    <li data-type="send_form">Submit form</li>
    <li data-type="if_element_is_defined">Continue if HTML contains element</li>
    <li data-type="if_element_is_not_defined">Continue if HTML doesn't contain element</li>
    <li data-type="if_text_is_defined">Continue if there is text</li>
    <li data-type="if_text_is_not_defined">Continue if there is no text</li>
  </ul>
</body>
Ahmad MRF
  • 1,346
  • 1
  • 6
  • 16
  • 1
    Thanks a lot, this actually works, I chose using the second variant. My mistake was using `'max-height'` property instead of `maxHeight` in the script, also using a class instead of data-iscollapsed is so much better. Would like to point out that using overflow and transition twice in .open isn't necessary, and, for future viewers, that you should set max-height of .open to the actual content length so there won't be a delay scrolling through empty pixels, in my case, 12em, and not 1000px, ironically – horart Apr 22 '22 at 18:04
0

height: 100% in this context doesn't really bring any meaning: as it's not dependent on a height of some parent element, it's basically the same as height: auto and you can't animate using height:auto. Now, considering that you are already using .js, before animating the element you can first set its innate height in pixels that you want to animate to:

const ul = document.querySelector("ul")
const btn = document.querySelector("button")

//the important part:
ul.style.height = ul.scrollHeight + "px"

btn.addEventListener("click", ()=>ul.classList.toggle("open"))
ul{
  display: block;
  overflow: hidden;
  transition: height 1s;
  background: #ddd;
}

ul:not(.open){
  height: 0 !important;
}
<button>Click</button>
<ul>
  <li>Some elements</li>
  <li>To show</li>
</ul>
Michał Sadowski
  • 1,946
  • 1
  • 11
  • 24