table 上的 Flexbox 在 Firefox 中不起作用

Flexbox on table doesn't work in Firefox

使用 flexbox 控制 table 的布局在 webkit 浏览器中有效,但在 Firefox 中,<td>s 仅呈现与其自身内容一样宽的宽度。

示范: http://codepen.io/afraser/pen/wMgbzr?editors=010

* {
  box-sizing: border-box;
}
table {
  border: 1px solid #ddd;
  width: 100%;
}
tbody {
  background: #fff;
}
tr {
  display: flex;
}
td:first-child {
  flex: 1 1 80%;
  background: mistyrose;
}
td:nth-child(2) {
  flex: 0 0 10%;
  background: Aquamarine;
}
td:nth-child(3) {
  flex: 0 0 10%;
  background: pink;
}
<table>
  <tbody>
    <tr>
      <td>Ted</td>
      <td>1</td>
      <td>100%</td>
    </tr>
    <tr>
      <td>Turd Ferguson</td>
      <td>2</td>
      <td>65%</td>
    </tr>
    <tr>
      <td>Hingle McKringleberry</td>
      <td>3</td>
      <td>99%</td>
    </tr>
  </tbody>
</table>

我尝试了几种变体,包括:

我在这里没有看到任何记录:https://github.com/philipwalton/flexbugs 并且在其他地方已经干涸了。有谁知道是怎么回事吗?

我认为问题涉及弹性项目的默认 display 值。

如果您用 display: flex 覆盖它,布局应该可以跨浏览器正常工作。

进行以下调整:

td:first-child  { display: flex; }
td:nth-child(2) { display: flex; }
td:nth-child(3) { display: flex; }

Revised Codepen

我的第一个想法是确保每个 td 都应用了正确的 display 值——类似于 display: flex-item 的值。但是 flex-item 不存在,所以我使用了 display: flex.


编辑

以上方案成立。此编辑属于说明。

在检查 spec 时,弹性项目似乎甚至没有默认的 display 值。基本上,一旦您将父容器设为弹性容器,子容器就会成为弹性项目,并接受弹性属性,而不管应用任何 display 规则。因此,不需要默认的 display 规则。

在这种情况下,似乎必须在 flex 项目上声明 display: flex 是让 Firefox 和 IE 正常工作所必需的怪癖。

这是因为,根据 CSS tables,当表格元素不是 table:

的子元素时,应该生成 anonymous table objects

根据 Flexbox Last Call Working Draft,是匿名 table 成为弹性项目,而不是 table 单元格:

Some values of display trigger the creation of anonymous boxes around the original box. It’s the outermost box—the direct child of the flex container box—that becomes a flex item. For example, given two contiguous child elements with display: table-cell, the anonymous table wrapper box generated around them [CSS21] becomes the flex item.

由于 table 单元格不是弹性项目,因此它们忽略了 flex 属性。它会应用于匿名 table,但 CSS select 或者不能 select 匿名元素。

但是,Chrome 不同意该规范,并决定改为屏蔽 table 单元格。

然后 CSS 工作组 decided 标准化 Chrome 的行为:

If you have a flex container and you put two table cells in it, they won't become flex items independently. They'll wrap in an anonymous table and that will be flex.

However, Chrome had implemented it so that each item is independently a flex item. [...] So it turns the table cells into blocks.

I've seen at least one presentation at a conference where they took advantage of this to create fallback behavior for a flex. [...] If you're not trying to trigger fallback, I don't know why you'd put a bunch of table cells in flex and get it wrapped in anonymous stuff. [...]

RESOLVED: Just blockify the children of flex and grid containers. Don't do anonymous box fix-up

first Flexbox Candidate Recommendation 以新分辨率发布:

Some values of display normally trigger the creation of anonymous boxes around the original box. If such a box is a flex item, it is blockified first, and so anonymous box creation will not happen. For example, two contiguous flex items with display: table-cell will become two separate display: block flex items, instead of being wrapped into a single anonymous table.

然后 Firefox 从版本 47 (bug 1185140) 开始实施了新行为。

对于旧版本,您可以手动将单元格样式设置为块:

.flex-container > td {
  display: block;
}

* {
  box-sizing: border-box;
}
table{
  border: 1px solid #ddd;
  width: 100%;
}
tbody {
  background: #fff;
}
tr {
  display: flex;
}
td {
  display: block;
}
td:first-child {
  flex: 1 1 80%;
  background: mistyrose;
}
td:nth-child(2){
  flex: 0 0 10%;
  background: Aquamarine;
}
td:nth-child(3){
  flex: 0 0 10%;
  background: pink;
}
<table>
  <tbody>
    <tr>
      <td>Ted</td>
      <td>1</td>
      <td>100%</td>
    </tr>
    <tr>
      <td>Turd Ferguson</td>
      <td>2</td>
      <td>65%</td>
     </tr>
    <tr>
      <td>Hingle McKringleberry</td>
      <td>3</td>
      <td>99%</td>
     </tr>
  </tbody>
</table>