I have an <img> with a panel to its right containing a controls header and a long list of items. So I have a nested flexbox situation:
.container (flex)
-> .child img
-> .child controls panel (flex)
-> .controls
-> .content-wrapper scrolling list
At a very basic level, the two side by side panels are easy, being a simple flex with align-items: stretch .. https://codepen.io/neekfenwick/pen/MOxYxz
At that basic level it's a duplicate question to How do I keep two divs that are side by side the same height?.
Once the panel on the right becomes more complex with a vertically scrolling list, I cannot see how to make the height of its parent, the second .child, match the height of the first .child. https://codepen.io/neekfenwick/pen/XzGJGw
+-------------+---------------+
| | Controls |
| Left child | |
| +---------------+
| | A|
| | Vertically |+
| | scrolling ||
| | items ||
| | |+
| | V|
+-------------+---------------+
I have read Flexbox item with scrollable content but that solves a horizontal scrolling problem, not a vertical layout like this. Also Nested flexbox with scrolling area deals with vertically stacked nested flexboxes, I think this combination of row and column directions confuses my situation.
As a code snippet:
.container {
display: flex;
align-items: stretch;
}
.child {
border: 1px solid grey;
background-color: lightgrey;
flex: 1 1 auto;
}
.controls-panel {
display: flex;
flex-direction: column;
}
.controls {
flex: 0 0 auto;
}
.content-wrapper {
flex: 1 1 auto;
width: 400px;
overflow-y: auto;
}
.content-item {
display: inline-block;
width: 100px;
height: 100px;
background-color: red;
}
<div class="container">
<div class="child">
<p>In real life I am an inline img.</p>
<p>I am some content whoop de doo.</p>
<p>I am some content whoop de doo.</p>
<p>I am some content whoop de doo.</p>
<p>I want my sibling to equal my height.</p>
</div>
<div class="child controls-panel">
<div class="controls">
<p>Small controls area. Panel below should scroll vertically.</p>
</div>
<div class="content-wrapper">
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
</div>
</div>
</div>
I do not want to fix the height of any elements here. As it happens, I know the height of the img, and so I could use CSS to force the height of the elements on the right, but I wondered if there is a 'true' flexbox way of solving this problem.
In general, for overflow: scroll (or auto and hidden) to work, a height constraint is needed in one way or the other, or else element's normally grow as much as needed to fit their content.
There is mainly 3 ways, where either an actual height is set, as in this first sample, where I added it to the container.
Stack snippet 1
.container {
display: flex;
height: 100vh;
}
.child {
border: 1px solid grey;
background-color: lightgrey;
flex: 1 1 auto;
}
.controls-panel {
display: flex;
flex-direction: column;
}
.controls {
flex: 0 0 auto;
}
.content-wrapper {
flex: 1 1 auto;
width: 400px;
overflow-y: auto;
}
.content-item {
display: inline-block;
width: 100px;
height: 100px;
background-color: red;
}
<div class="container">
<div class="child">
<p>In real life I am an inline img.</p>
<p>I am some content whoop de doo.</p>
<p>I am some content whoop de doo.</p>
<p>I am some content whoop de doo.</p>
<p>I want my sibling to equal my height.</p>
</div>
<div class="child controls-panel">
<div class="controls">
<p>Small controls area. Panel below should scroll vertically.</p>
</div>
<div class="content-wrapper">
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
</div>
</div>
</div>
Or to use absolute positioning to create that height constraint, which an absolute element does.
It is simply accomplished with an extra wrapper, content-scroll, and will keep the rest of the structure fully dynamic.
Stack snippet 2
.container {
display: flex;
}
.child {
border: 1px solid grey;
background-color: lightgrey;
flex: 1 1 auto;
}
.controls-panel {
display: flex;
flex-direction: column;
}
.controls {
flex: 0 0 auto;
}
.content-wrapper {
position: relative;
flex: 1 1 auto;
width: 400px;
}
.content-scroll {
position: absolute;
top: 0; left: 0;
right: 0; bottom: 0;
overflow-y: auto;
}
.content-item {
display: inline-block;
width: 100px;
height: 100px;
background-color: red;
}
<div class="container">
<div class="child">
<p>In real life I am an inline img.</p>
<p>I am some content whoop de doo.</p>
<p>I am some content whoop de doo.</p>
<p>I am some content whoop de doo.</p>
<p>I want my sibling to equal my height.</p>
</div>
<div class="child controls-panel">
<div class="controls">
<p>Small controls area. Panel below should scroll vertically.</p>
</div>
<div class="content-wrapper">
<div class="content-scroll">
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
</div>
</div>
</div>
</div>
Use Flexbox alone, thought it might not work fully cross browsers, especially with older versions, that still support it but is a lot buggier.
The simple fix in your original code is to change the flex: 1 1 auto; in .content-wrapper to flex: 1 1 0px; (0px were needed for my IE version, for Chrome/Firefox/Edge one can use 0)
Stack snippet 3
.container {
display: flex;
}
.child {
border: 1px solid grey;
background-color: lightgrey;
flex: 1 1 auto;
}
.controls-panel {
display: flex;
flex-direction: column;
}
.controls {
flex: 0 0 auto;
}
.content-wrapper {
flex: 1 1 0px;
width: 400px;
overflow-y: auto;
}
.content-item {
display: inline-block;
width: 100px;
height: 100px;
background-color: red;
}
<div class="container">
<div class="child">
<p>In real life I am an inline img.</p>
<p>I am some content whoop de doo.</p>
<p>I am some content whoop de doo.</p>
<p>I am some content whoop de doo.</p>
<p>I want my sibling to equal my height.</p>
</div>
<div class="child controls-panel">
<div class="controls">
<p>Small controls area. Panel below should scroll vertically.</p>
</div>
<div class="content-wrapper">
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
<div class="content-item"></div>
</div>
</div>
</div>
Snippet 2 and 3 also answers your question
...with a vertically scrolling list, I cannot see how to make the height of its parent, the second
.child, match the height of the first.child.
Note, if the top element in the right column can grow bigger than the left column, a minimum height will be needed on the bottom element, to prevent it from collapse into 0, e.g.
.content-wrapper {
...
min-height: 200px; /* e.g. like this */
}
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