<div>
  <button class="button">Collapse</button>
  
  <div class="content">
    <p class="collapsible">
This is a block of text that is collapsed through JavaScript. It is more complicated than using max-height with similar performance. The transition timings are now fixed but we've introduced some coupling between our CSS and JS.
    </p>
    <p>
Praesent nec feugiat enim. In vitae elementum erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vitae lectus varius ipsum tempor maximus in ac eros. Mauris lacus lorem, elementum non lacus vitae, interdum commodo odio.
    </p>
  </div>
</div>
.collapsible {
  overflow: hidden;
  transition: all 0.5s ease-in-out;
  height: auto;
}

.collapsible.collapsed {
  height: 0;
}
const button = document.querySelector('.button');

button.addEventListener('click', () => {
  const content = document.querySelector('.collapsible');
  expandElement(content, 'collapsed');
});

function expandElement(elem, collapseClass) {
  // debugger;
  elem.style.height = '';
  elem.style.transition = 'none';
  
  const startHeight = window.getComputedStyle(elem).height;
  
  // Remove the collapse class, and force a layout calculation to get the final height
  elem.classList.toggle(collapseClass);
  const height = window.getComputedStyle(elem).height;
  
  // Set the start height to begin the transition
  elem.style.height = startHeight;
  
  // wait until the next frame so that everything has time to update before starting the transition
  requestAnimationFrame(() => {
    elem.style.transition = '';
    
    requestAnimationFrame(() => {
        elem.style.height = height
    })
  })
  
  // Clear the saved height values after the transition
  elem.addEventListener('transitionend', () => {
    elem.style.height = '';
    elem.removeEventListener('transitionend', arguments.callee);
  }); 
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.