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) {
...