0

I'm trying to animate an element's height from a preset one to the one that's dependent on what's inside (what height: auto would set). Because an animation doesn't work for height: auto (going to or from) I thought a solution could be to save the current height, set height: auto on an element to get the final height and save that, then reset the element's height to initial and then set it to the final height. The "blink to auto" the user wouldn't notice and the last change should result in an animation.

const containerBlockDiv = document.querySelector('.container-block')
const childBlockDiv = document.querySelector('.child-block')

const containerCurrentHeight = containerBlockDiv.scrollHeight
containerBlockDiv.style.height = 'auto'
const containerNewHeight = containerBlockDiv.scrollHeight
containerBlockDiv.style.height = `${containerCurrentHeight}px`
containerBlockDiv.style.height = `${containerNewHeight}px`
.container-block {
  display: inline-block;
  background-color: red;
  height: 50px;
  width: 20px;
  transition: height 1s;
}

.child-block {
  display: inline-block;
  height: 100px;
}
<div class="container-block">
  <div class="child-block"></div>
</div>

Why doesn't this work?

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
Stefan Bajić
  • 374
  • 4
  • 14
  • 1
    I'm pretty sure transitions don't work on styles set via Javascript, first of all. I would use JS to add a class and set the styles you want for that class using CSS. – kdsprogrammer Feb 23 '21 at 15:21
  • 1
    Use `max-height` for animation here, not `height` and then you can set the `height:auto` with no issue. – Scott Marcus Feb 23 '21 at 15:22
  • They do https://codepen.io/warhammered_cat/pen/yLVPXRV. @kdsprogrammer – Stefan Bajić Feb 23 '21 at 15:33
  • @StefanBajić cool, learned something new today – kdsprogrammer Feb 23 '21 at 15:35
  • All the CSSOM ever sees here is the last `containerBlockDiv.style.height = \`${containerNewHeight}px\``. You need to force it to parse the intermediate value, by forcing what's called a reflow between the two value settings. https://jsfiddle.net/2anv6gru/ – Kaiido Mar 09 '21 at 07:48
  • If it only sees the last value, why doesn't it animate between the first value and the last? @Kaiido – Stefan Bajić Mar 09 '21 at 09:20
  • 1
    Because it doesn't even see the first value. It can't transition from nothing. – Kaiido Mar 09 '21 at 10:14
  • What do you mean it doesn't see the first value? The height is defined to be 50px in .container-block? If it sees that and sees the last one containerBlockDiv.style.height = `${containerNewHeight}px` it should be able to animate between them? @Kaiido – Stefan Bajić Mar 09 '21 at 11:58
  • 1
    I mean it doesn't even see the 50px value either. Your script runs before the first reflow. Read the accepted answer in the linked question and all the linked answers from there, I've written enough about this I think. – Kaiido Mar 09 '21 at 12:00
  • Thank you for taking time to help me out. @Kaiido – Stefan Bajić Mar 09 '21 at 13:25

1 Answers1

1

Here's what I have in my spellbook to animate a div from 0 (or any other fixed value) to auto : pure CSS, no JS

div {
  max-height: 15px;
  overflow: hidden;
  border: red dashed 1px;
  transition: max-height 0.3s cubic-bezier(0, 1, 0, 1);
}

div:hover {
  max-height: 9999px;
  transition: max-height 0.3s cubic-bezier(1, 0, 1, 0);
}
<div>Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some
  content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content
  Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content Some content</div>
Jeremy Thille
  • 26,047
  • 12
  • 43
  • 63
  • 1
    I don't like this approach, because to quote CSS tricks: "The transition length will not actually be what you specify unless the content height works out to be exactly the same as max-height". Anyway, I asked why what I tried doesn't work, not for an alternative approach. – Stefan Bajić Feb 23 '21 at 15:30