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