javascripthtmlcssanimationslide

How can I change a div to another with animation?


I have a checkbox that should change which part of the form is showed. Actually, it's just appear/disappear by using display: none;. I tried to add animation like that:

function change(event) {
  document.getElementById('part1').style.display = (event.target.checked ? null : 'none');
  document.getElementById('part2').style.display = (event.target.checked ? 'none' : null);
}
.animated {
  transition: all 300ms ease-in;
}
<div>
  <label for="my-check">Click here</label>
  <input type="checkbox" name="my-check" onchange="change(event)">
</div>
<div>
  <div style="display: none;" class="animated" id="part1">
    <input type="text" name="thing1"><label for="thing1">Thing 1</label><br>
    <input type="text" name="thing2"><label for="thing2">Thing 2</label>
  </div>
  <div class="animated" id="part2">
    <select>
      <option>Else</option>
    </select>
  </div>
</div>
<hr>
<input type="text" name="other"><label for="other">Other</label>

But there is no valid animation. How can I make it to slide up new, and slide down old ?


Solution

  • The animation should be coupled with height edition. In this example, the first loop is to set default values, exactly like if the user already changed it. I set height: 0px; by default to the one that is hidden by default.

    for(const wrapper of document.querySelectorAll(".collapse-wrapper")) {
        if(wrapper.style.height != '0px') { // set real height
            const height = wrapper.querySelector(".collapse-content").getBoundingClientRect().height
            wrapper.style.height = `${height}px`;
        }
    }
    
    function change() {
        for(const wrapper of document.querySelectorAll(".collapse-wrapper")) {
            if(wrapper.style.height == '0px') {
                const height = wrapper.querySelector(".collapse-content").getBoundingClientRect().height
                wrapper.style.height = `${height}px`;
            } else {
                wrapper.style.height = '0px'
            }
        }
    }
    .collapse-wrapper {
        overflow: hidden;
        transition: height 300ms ease-in;
    }
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
    <div>
      <label for="my-check">Click here</label>
      <input type="checkbox" name="my-check" onchange="change()">
    </div>
    <div class="collapse-wrapper" style="height: 0px;">
      <div class="collapse-content">
        <input type="text" name="thing1"><label for="thing1">Thing 1</label><br>
        <input type="text" name="thing2"><label for="thing2">Thing 2</label>
      </div>
    </div>
    <div class="collapse-wrapper">
      <div class="collapse-content">
        <select>
          <option>Else</option>
        </select>
      </div>
    </div>
    <hr>
    <input type="text" name="other"><label for="other">Other</label>