I'm displaying a list of items. Each item has a header and some content. Each item's height expands/collapses when its header is clicked. The height of each item's content is dynamic.
I've got the following code (seen below) which works. However, there is a slight delay between the user clicking on .header and the transition beginning.
This delay appears to be introduced by my use of max-height: min-content. I believe the browser needs a moment to re-calculate the height of the content after the.isCollapsed class is added/removed.
I'm wondering if there's a more correct way to achieve this effect?
If I remove max-height: min-content then flex: 1 on .item causes each item to be the same height when expanded. This is not desired. I want each item's height to fit its contents.
I do not want a solution which requires me to measure the text in JavaScript or similar. The goal is to leverage flexbox to perform the transition without knowing the height of content.
$('.header').click(function() {
$(this).parent().toggleClass('isCollapsed');
});
*,
*::before,
*::after {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
}
ul,
li {
list-style: none;
margin: 0;
padding: 0;
}
.items {
display: flex;
flex-direction: column;
height: 100%;
flex: 1;
}
.item {
display: flex;
flex-direction: column;
overflow: hidden;
min-height: 48px;
transition: flex-grow 1s;
flex: 1;
max-height: min-content;
}
.header {
display: flex;
height: 48px;
padding: 16px;
align-items: center;
flex-shrink: 0;
}
.isCollapsed {
flex-grow: .001;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class='items'>
<li class='item'>
<div class='header'>Item A Header</div>
<div class='content'>Item A Content This content is</br>
really</br>
really</br>
really</br>
really</br>
long.
</div>
</li>
<li class='item'>
<div class='header'>Item B Header</div>
<div class='content'>
Item B Content This content is</br>
short.
</div>
</li>
</ul>
In the following code block there's some room for greater efficiency.
.item {
display: flex;
flex-direction: column;
overflow: hidden;
min-height: 48px;
transition: flex-grow 1s;
flex: 1;
max-height: min-content;
}
You're using min-height and flex. But with flex, you don't really need min-height.
Try this instead:
.item {
display: flex;
flex-direction: column;
overflow: hidden;
/* min-height: 48px; */
transition: flex-grow 1s;
flex: 1 0 48px; /* adjusted */
max-height: min-content;
}
The delay is gone on my end.
DEMO
I also corrected the <br> tags (</br> is not valid).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With