CSS: Flexbox最后一行高度翻倍

4
我用 flexboxes 玩了一下,并尝试用 top/mid/bottomrule 模仿 LaTeX 表格。我喜欢这个表格可以在小屏幕上适应,变成列表。然而,我发现如果在一个单元格的文本内容中使用空格,该单元格的高度可能会翻倍甚至翻三倍,且没有明显原因。是否有我忽略的 flexbox 属性可以帮助我修复此行为?为什么会产生这种额外的高度?截图请看:enter image description here

Snippet:

div.table {
  display: flex;
  flex-flow: column wrap;
  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>


将Cell2之间加上一个空格(变成“cell 2”),问题在于单词之间的空格。 - El0din
请注意,最后一行的高度并没有加倍(正如您标题中所述)。而是第二行的高度加倍了。 - Michael Benjamin
2个回答

3
问题在于,最初,.row 的大小仅考虑了 .item 的内容。然后,.item 进行了弹性布局,并由于 flex: 1 变得等宽。但是内容的宽度不相等,因此最长的会换到第二行。
这个例子可以更好地说明:

.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>

在你的例子中,你有带空格的Cell 1和不带空格的Cell2,这就产生了差异。
最终.row也会弹性伸展,因此不再需要新行,但浏览器似乎无法检测到。很难说,但我认为是这样。这是因为。
  1. 假设性的主要尺寸(高度)被计算出来,

    如果需要交叉尺寸以确定主要尺寸(例如当 flex 项的主要尺寸在其块轴上时),且 flex 项的交叉尺寸为自动且不明确,则在此计算中使用 fit-content 作为 flex 项的交叉尺寸。

  2. 行的弹性。这决定了它们所使用的高度。

  3. 交叉尺寸(宽度)被确定。行被拉伸以水平填充表格。但现在为时已晚,高度已经被计算出来了。
由于您的列布局不会换行,因为.table具有自动高度,因此我将只使用默认的flex-wrap:nowrap。它可以解决问题,因为现在flex容器将是单行的,因此行的宽度将是definite

如果单行flex容器具有确定的交叉尺寸,则拉伸的任何flex项目的外部交叉尺寸是flex容器的内部交叉尺寸(被钳制到flex项目的最小和最大交叉尺寸)并且被视为明确。

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>

您也可以尝试显式提供一个明确的宽度:

div.row {
  width: 100%;
}

或者使用 whitespace: nowrap 防止文本换行。


为什么这种行为不会在第一行或第三行发生? - Michael Benjamin
@Michael_B 因为在其他行中,flex之前两个.item的宽度是相同的。 - Oriol
@Michael_B 你也需要一些空间(软换行机会),或者 word-break: break-all 来在单词内部断行。 - Oriol
是的,我早就注意到空格字符很重要了。只是不确定为什么。感谢您提供的精彩解释。 - Michael Benjamin
此外,只是提供信息,Edge 和 IE11 可以检测和调整 flex 布局,从而呈现预期的布局。 - Michael Benjamin
@Oriol 感谢您的回复!.row{width:100%}.table{flex-flow: column}都可以解决问题,并且似乎会导致相同的输出。但是,由于.row{width:100%}基本上是修复了错误的wrap命令,我更喜欢.table{flex-flow: column}的解决方案。由于我希望项目在行中换行,单词在项目中换行,因此whitespace: nowrap对我来说不是解决方案。 - Julian

0

只需将 div.item 中的 flex: 1; 更改为仅使用 flex-grow:1;

这是可工作的代码片段。

div.table {
  display: flex;
  width: 70%;
  margin: 15px auto;
  border-bottom: 2px solid black;
}
div.row {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}
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-grow: 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>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接