Using HTML and JavaScript I am trying to create a list that transitions into view when a button is clicked, including a scrollable inner container, using a max-height transition on the parent DIV.
However, while the parent div transitions smoothly, the content instantly appears after the transition completes. It seems to occur when the inner div is overflowing.
I am aware that removing the inner div, removing its overflow property or constraining its height to the parent will stop the symptoms from occuring, but I want to keep the inner div scrollable and I’m not sure why I can’t.
Here is an example of what I have been attempting.
let visible = false;
function showHideList() {
const listContainerRef = document.getElementById('list-id');
if (!listContainerRef?.style?.maxHeight)
return;
listContainerRef.style.maxHeight = visible ? 0 + 'px' : 200 + 'px';
visible = !visible;
}
<button onclick="showHideList()" style="padding: 1rem; background: #2aabd2">Show / Hide</button>
<div id="list-id" style="transition: max-height 2s linear; overflow: hidden; max-height: 0;">
<div style="overflow: auto; max-height: 200px">
<div style="background-color: green">
<span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 1</span>
<span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 2</span>
<span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 3</span>
<span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 4</span>
<span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 5</span>
<span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 6</span>
</div>
</div>
</div>
Here is another example:
#list-container {
max-height: 0;
transition: max-height 2s ease-out;
overflow: hidden;
}
#list-container.visible {
max-height: 300px;
}
#list-content {
max-height: 200px;
overflow: auto;
}
li {
background-color: red;
padding: 0.5rem 0.75rem;
}
button {
padding: 1rem;
background: #2aabd2;
}
<button onclick="document.getElementById('list-container').classList.toggle('visible')">Show / Hide</button>
<div id="list-container">
<div id="list-content">
<ul>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
</ul>
</div>
</div>
2
Answers
Please see the answer by Fabrizio Calderan for arguably the correct solution.
For sake of completeness though, this is closer to what I originally had in mind: using clip-path instead of max-height and overflow. This avoids the scrollbar appearing unnecessarily and vanishing instantly while transitioning - if the final content is less than the end height / max-height.
It seems that the issue is caused by
overflow: auto
in the intermediate wrapper: here is a version of a scrollable list, without that wrapper and using an unordered listul
instead of adiv
.Instead of using
max-height
as an inline style I used a custom property (--mh
) set to0
by default in the style, so the Javascript code can be simplified a bit.