0

I cannot determine why the specified transition is not applied when I toggle the max-height of the unordered list. The toggle is accomplished by switching classes on the UL. I've tried putting the transition in the max-height classes, but to no avail. I've created a working example on JSFiddle, and the code is supplied below in full. Thanks in advance for any help.

<!DOCTYPE html>
<html lang=en>
<head>
    <title>Transition Problem</title>
<style>
.nav ul {
    overflow: hidden;
    transition: max-height 2s;
    -webkit-transition: max-height 2s;
    white-space: normal;
}

.max-height-150 {
    max-height: 150px;
}

.max-height-none {
    max-height: none;
}
</style>
</head>
<body>
<p>The JavaScript switches the class correctly, and the height of the UL switches as expected, but the transition is not applied.</p>
<button>SWITCH CLASS</button>
<nav class="nav">
    <ul class="max-height-150">
        <li>Item 1</li>
        <li>Item 2</li>
        <li>Item 3</li>
        <li>Item 4</li>
        <li>Item 5</li>
        <li>Item 6</li>
        <li>Item 7</li>
        <li>Item 8</li>
        <li>Item 9</li>
        <li>Item 10</li>
        <li>Item 11</li>
        <li>Item 12</li>
        <li>Item 13</li>
        <li>Item 14</li>
        <li>Item 15</li>
        <li>Item 16</li>
        <li>Item 17</li>
        <li>Item 18</li>
        <li>Item 19</li>
    </ul>
</nav>
<script>
// Select the button:
var button = document.getElementsByTagName('button')[0];

// Toggle between the two max-height classes when the button is clicked:
var buttonClickListener = function (e) {
    var navUl = document.querySelectorAll('.nav ul')[0];
    if (navUl.classList.contains('max-height-150')) {
        navUl.classList.remove('max-height-150');
        navUl.classList.add('max-height-none');
    } else {
        navUl.classList.add('max-height-150');
        navUl.classList.remove('max-height-none');
    }
    e.preventDefault();
};

// Add a click listener on the button and register the toggle function on it:
if (button.addEventListener) {
    button.addEventListener('click', buttonClickListener, false);
} else if (button.attachListener) {
    button.attachEvent('click', buttonClickListener);
}
</script>
</body>
</html>
Tom
  • 1,836
  • 4
  • 16
  • 30

2 Answers2

2

Unfortunately you cannot transition from a set max-height to none (or auto, or 100%, etc). You can only transition between set numbers. Try setting the new max height to the largest value you believe it will have and it should work the way you want.

.max-height-none {
    max-height: 350px;
}

Updated fiddle: https://jsfiddle.net/07cgn26r/1/

Joe Zeleny
  • 884
  • 7
  • 10
  • Thanks! The only problem is that the beginning of the transition from a greater max-height to a lesser max-height has a "delay" that is actually time spent covering the difference between the actual height of the element and the max-height specified. (e.g., try max-height: 10000px instead of 350px). Is there a way to add the max-height dynamically (to the true full height) with JavaScript and still obtain the transition effect? – Tom May 25 '17 at 16:13
0

Use the viewport!

.max-height-none {
    max-height: 100vh;
}
rupumped
  • 209
  • 1
  • 11
  • Thanks, but sadly, this won't work if the content is taller than the viewport. I need it to open to reveal the complete content, regardless of the height of the content. – Tom May 20 '22 at 05:38