Equal height rows in a flex container
The answer is NO.
The reason is provided in the flexbox specification:
6. Flex Lines
In a multi-line flex container, the cross size of each line is the minimum size necessary to contain the flex items on the line.
In other words, when there are multiple lines in a row-based flex container, the height of each line (the "cross size") is the minimum height necessary to contain the flex items on the line.
Equal height rows, however, are possible in CSS Grid Layout:
- Equal height rows in CSS Grid Layout
Otherwise, consider a JavaScript alternative.
Using flexbox for equal height rows when split in columns
Make two adjustments to make the layout work.
Add this to your code:
.flex-rows {
flex: 1; /* gives this container the height of its parent */
}
.row-flex:last-child {
margin-top: auto; /* spaces siblings away to the extremes;
.row-flex:first-child { margin-bottom: auto } would also work;
and so would justify-content: space-between on the container
(which would save you from having to create this new rule; */
}
In the revised code below, I've commented out what appear to be unnecessary rules.
.flex-cols { display: flex; /* width: 100%; */ /* flex-direction: row; */}
.col-flex { display: flex; flex: 1; /* flex-basis: 100%; */ flex-direction: column; margin-right: 20px; border: 1px solid green; padding: 5px;}
.flex-rows { flex: 1; /* ADDITION #1 */ display: flex; /* width: 100%; */ flex-direction: column;}
.row-flex { border: 1px solid red; display: flex; /* flex: 1; */ /* flex-basis: 100%; */ flex-direction: column; margin-bottom: 20px;}
.row-flex:last-child { margin-top: auto; /* ADDITION #2 */}
<div class="flex-cols"> <div class="col-flex"> <div class="flex-rows"> <div class="row-flex"> Hello </div> <div class="row-flex"> World </div> </div> </div> <div class="col-flex"> <div class="flex-rows"> <div class="row-flex"> Hello, hello, hello! This is a bunch of extra text to explain what should happen. Ideally, this will take up as much room as needed, and the div below will take up an equal amount to force a vertical 50/50 split. </div> <div class="row-flex"> World </div> </div> </div> <div class="col-flex"> <div class="flex-rows"> <div class="row-flex"> Hello </div> <div class="row-flex"> World </div> </div> </div></div>
CSS Flex: How to get equal heights in flex rows
flex-grow
works this way: it takes available space and distributes it only after applying flex-basis
(which when auto
takes its value from width
or height
, in current case it's height
because of flex-direction: column
). In current case flex-basis
is auto
because height
is also
. If after applying flex-basis
no free space will remain, flex-grow
won't work.
So you have several options here: set height: 0
or set flex-basis: 0
. Also you might need min-height: 0
(because min-height: auto
in some cases don't allow flex-item to occupy less then its content).
Demo:
.row-container { display: flex; flex-direction: column; height: 300px; width: 75%; border: 1px solid blue;}
.flex-row { border: 1px solid black; flex-grow: 1; flex-basis: 0; /* or height: 0; */ /* if needed add min-height: 0; */ display: flex; background-color: yellow; align-items: center;}
.col-1,.col-2 { border: 1px solid green;}
.col-right { padding-left: 10px;}
<div class="some-div"> <div class="row-container"> <div class="flex-row"> <div class="col-wrapper"> <div class="col-1">X</div> <div class="col-2">some content</div> </div> </div> <div class="flex-row"> <div class="col-wrapper"> <div class="col-1">XXX</div> <div class="col-2">some longer content</div> </div> </div> <div class="flex-row"> <div class="col-wrapper"> <div class="col-1">aa ab</div> <div class="col-2">Amet illo distinctio facilis blanditiis alias. Explicabo dolores asperiores ducimus aut officiis, vero? Accusantium in accusantium ipsa iusto velit? Quas nesciunt ipsam amet impedit adipisci odio Omnis nemo perspiciatis quibusdam</div> </div> </div> </div></div>
Give equal height to children of elements within a flex container
The flex properties on the parent container (container
in your example) don't pass down to the child elements, even if they are also containers. Therefore you also need to make the col
divs display:flex
, as follows:
.col {
flex: 1;
display: flex; /* make this a flex container so it has flex properties */
justify-content: center; /* to horizontally center them in this flex display */
/* REST OF YOUR CSS HERE */
}
Note that you also need to add flex: 1;
to the content itself so it doesn't shrink, e.g.:
.col-item {
flex: 1;
/* REST OF YOUR CSS HERE */
}
Working Example with your code:
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-content: center;
}
.col {
flex: 1;
background: orange;
margin: 1px;
display: flex;
justify-content: center;
}
.col-item {
flex: 1;
margin: 15px;
}
<html>
<body>
<div class="container">
<div class="col">
<div class="col-item" style="background: red;">
<h2>Column 1</h2>
<p>Hello World</p>
</div>
</div>
<div class="col">
<div class="col-item" style="background: red;">
<h2>Column 2</h2>
<p>Hello World!</p>
<p>Hello World!</p>
<p>Hello World!</p>
<p>Hello World!</p>
</div>
</div>
<div class="col">
<div class="col-item" style="background: red;">
<h2>Column 3</h2>
<p>Some other text..</p>
<p>Some other text..</p>
</div>
</div>
</div>
</body>
</html>
Equal height sections within flexbox columns?
Since both columns are inside the same flex container, yes, the list boxes can be the same height (based on the tallest content) using only CSS.
.columns { display: flex;}
.col { display: flex; /* new */ flex-direction: column; /* new */ margin-left: 20px;}
.list { flex: 1; /* new */ padding: 24px; border: 1px solid blue;}
ul { margin: 0;}
<div class="columns"> <div class="col"> <h3>Header</h3> <div class="list"> <ul> <li>List item</li> <li>List item</li> </ul> </div> </div> <div class="col"> <h3>Header</h3> <div class="list"> <ul> <li>List item</li> <li>List item</li> <li>List item</li> <li>List item</li> </ul> </div> </div></div>
Equal height rows in flex-direction: column
The flex equal height columns feature – which is the result of align-items: stretch
, a default setting of a flex container – applies only to flex items on the same row.
It doesn't work for items in a multi-line flex container. This behavior is defined in the spec:
6. Flex Lines
In a multi-line flex container (even one with only a single line), the
cross size of each line is the minimum size necessary to contain the
flex items on the line (after alignment due toalign-self
), and the
lines are aligned within the flex container with thealign-content
property.
In other words, when there are multiple lines in a row-based flex container, the height of each line (the "cross size") is the "minimum size necessary to contain the flex items on the line".
In addition, because align-items: stretch
works along the cross-axis, the equal height columns feature is useless in flex-direction: column
, where the cross-axis is horizontal.
To achieve equal height columns/rows across multiple lines consider a Javascript solution.
However, without knowing much about your overall objective, here's a simple way to achieve equal height rows in your current layout:
Add duplicate content in both divs. In the
.component.left
div, usevisibility: hidden
.
Revised Fiddle
Equal height rows in CSS Grid Layout
Short Answer
If the goal is to create a grid with equal height rows, where the tallest cell in the grid sets the height for all rows, here's a quick and simple solution:
- Set the container to
grid-auto-rows: 1fr
How it works
Grid Layout provides a unit for establishing flexible lengths in a grid container. This is the fr
unit. It is designed to distribute free space in the container and is somewhat analogous to the flex-grow
property in flexbox.
If you set all rows in a grid container to 1fr
, let's say like this:
grid-auto-rows: 1fr;
... then all rows will be equal height.
It doesn't really make sense off-the-bat because fr
is supposed to distribute free space. And if several rows have content with different heights, then when the space is distributed, some rows would be proportionally smaller and taller.
Except, buried deep in the grid spec is this little nugget:
7.2.3. Flexible Lengths: the
fr
unit...
When the available space is infinite (which happens when the grid
container’s width or height is indefinite), flex-sized (fr
) grid tracks are
sized to their contents while retaining their respective proportions.The used size of each flex-sized grid track is computed by determining
themax-content
size of each flex-sized grid track and dividing that
size by the respective flex factor to determine a “hypothetical1fr
size”.The maximum of those is used as the resolved
1fr
length (the
flex fraction), which is then multiplied by each grid track’s flex
factor to determine its final size.
So, if I'm reading this correctly, when dealing with a dynamically-sized grid (e.g., the height is indefinite), grid tracks (rows, in this case) are sized to their contents.
The height of each row is determined by the tallest (max-content
) grid item.
The maximum height of those rows becomes the length of 1fr
.
That's how 1fr
creates equal height rows in a grid container.
Why flexbox isn't an option
As noted in the question, equal height rows are not possible with flexbox.
Flex items can be equal height on the same row, but not across multiple rows.
This behavior is defined in the flexbox spec:
6. Flex Lines
In a multi-line flex container, the cross size of each line is the minimum size necessary to contain the flex items on the line.
In other words, when there are multiple lines in a row-based flex container, the height of each line (the "cross size") is the minimum height necessary to contain the flex items on the line.
Related Topics
Why Does This Inline-Block Element Have Content That Is Not Vertically Aligned
How to Make a Whole Row in a Table Clickable as a Link
Why Does Position:Relative; Appear to Change the Z-Index
Using ≪Style≫ Tags in the ≪Body≫ With Other Html
How to Customize ≪Input Type="File"≫
How to Encode/Decode HTML Entities in Ruby
How to Add an Image to an Event With Microdata Meta Tag
How to Create Custom Tags For Html
Twitter Bootstrap 3, Vertically Center Content
How to Display Just a Portion of an Image in Html/Css
Curve Bottom Side of the Div to the Inside With Css
Best Practices & Considerations When Writing HTML Emails
Freeze the Top Row For an HTML Table Only (Fixed Table Header Scrolling)
Add Border-Bottom to Table Row ≪Tr≫
Making a Div Vertically Scrollable Using Css
How to Include an HTML Page into Another HTML Page Without Frame/Iframe