The problem is that, initially, .row
is sized taking only the contents of .item
s into account. Then .item
s flex, and become equally wide due to flex: 1
. But the contents weren't equally wide, so the longest will wrap to a second line.
It's better shown in this example:
.row {
display: inline-flex;
margin: 2px;
}
.item {
border: 1px solid;
}
.flex {
flex: 1;
}
<div class="row">
<div class="item">Cell 11111</div>
<div class="item">Cell 2</div>
(before flex)
</div>
<br />
<div class="row">
<div class="item flex">Cell 11111</div>
<div class="item flex">Cell 2</div>
(after flex)
</div>
In your example you have Cell 1
(with space) and Cell2
(without), which produces the difference.
Eventually the .row
also flexes and thus a new line is no longer needed, but it seems browsers don't detect that. It's hard to say, but I think this is right. That's because
The hypothetical main size (height) of the rows is calculated, and
If a cross size is needed to determine the main size (e.g. when the
flex item’s main size is in its block axis) and the flex item’s cross
size is auto and not definite, in this calculation use fit-content as
the flex item’s cross size.
Rows flex. This determines their used height.
- Cross sizes (widths) are determined. The rows are stretched to fill the table horizontally. But its too late, heights have already been calculated.
Since your column layout won't wrap because .table
has an auto height, I would just use the default flex-wrap: nowrap
. It fixes the problem because now the flex container will be single-line, and thus the widths of the rows will be definite:
If a single-line flex container has a definite cross size, the outer
cross size of any stretched flex items is the flex container’s inner
cross size (clamped to the flex item’s min and max cross size) and is
considered definite.
div.table {
flex-flow: column;
}
div.table {
display: flex;
flex-flow: column;
width: 70%;
margin: 15px auto;
border-bottom: 2px solid black;
}
div.row {
display: flex;
justify-content: space-between;
flex-flow: row wrap;
}
div.head {
flex: 1;
text-align: center;
align-items: flex-start;
font-weight: bold;
border-width: 2px 0 1px;
border-style: solid;
}
div.item {
flex: 1;
text-align: center;
align-items: flex-start;
}
<div class="table">
<div class="row">
<div class="head">Col 1</div>
<div class="head">Col 2</div>
</div>
<div class="row">
<div class="item">Cell 1</div>
<div class="item">Cell2</div>
</div>
<div class="row">
<div class="item">Cell 3</div>
<div class="item">Cell 4</div>
</div>
</div>
You can also try explicitly providing an explicit width:
div.row {
width: 100%;
}
Or even preventing text wrapping with whitespace: nowrap
.