transitionrun for max-height

by EoghanM

HTML

<div class="trigger">
Hover Me <span id="info"></span>
  <div class="drawer">
    <ul>
      <li>Monk</li>
      <li>Sage</li>
      <li>Warlock</li>
      <li>Evergreen</li>
      <li>Onyx</li>
      <li>Leathrom</li>
      <li>Gathering</li>
    </ul>
  </div>
</div>

<div class="drawer auto-toggle-drawer">
  <ul>
    <li>Zebra</li>
    <li>Lion</li>
    <li>Koala</li>
    <li>Parakeet</li>
    <li>Oryx</li>
    <li>Rhino</li>
    <li>Antelope</li>
  </ul>
</div>

CSS

.drawer {
  border: 1px solid green;
  max-height: 50em;
  overflow: hidden;
  transition: max-height 1s ease-in-out;
}

.trigger:not(:hover) .drawer,
.drawer.closed {
  max-height: 0 !important;
}

.drawer.closed li {
  color: red;
}

JavaScript

setInterval(function() {
    document.getElementsByClassName('auto-toggle-drawer')[0].classList.toggle('closed');
}, 3000);

// start max-height -> height polyfill
(function() {
  var style = document.createElement("style");
  style.appendChild(document.createTextNode("[height-locked] { height: 0 !important;}"));
  document.head.appendChild(style);

    function test_direction(el, starting_maxh) {
	var self = function() {
	    var cs = getComputedStyle(el);
	    if (cs['maxHeight'] == starting_maxh) {
		requestAnimationFrame(self);
	    } else {
		var tr = cs['transition'];
		if (cs['maxHeight'] < starting_maxh) {
		    // shrinking
		    if (el.style.height == '') {
			el.style.height = cs['height'];
			document.getElementById('info').innerHTML = 'from shrink: ' + el.style.height;
			void el.offsetWidth; // needed for transition to 'take'
			console.log('shrink', cs['maxHeight'], starting_maxh, cs['height']);
		    } else {
			console.log('reshrink', cs['maxHeight'], starting_maxh);
		    }
		    el.setAttribute('height-locked', true);
		} else {
		    // growing
		    console.log('grow', el.scrollHeight);
		    el.setAttribute('height-locked', true);
		    el.style.height = el.scrollHeight + 'px';
		    void el.offsetWidth; // transition happens now between zero (heigh-locked) to style.height
		    el.removeAttribute('height-locked');
		    document.getElementById('info').innerHTML = 'from grow: ' + el.scrollHeight + 'px';
		}
	    }
	}
	// need requestAnimationFrame to detect the direction of the max-height transition
	requestAnimationFrame(self);
    }

    document.addEventListener('transitionstart', function(e) {
	if (e.propertyName == 'max-height') {
	    var el = e.target;
	    if (el.hasAttribute('height-locked')) {
		el.removeAttribute('height-locked');
	    } else {
		var cs = getComputedStyle(el);
		var tr = cs['transition'];
		var add_h_transition = tr.match(/max-(height[^,]+)/)[1];
		if (el.style.transition.indexOf(add_h_transition) === -1) {
		   ...