【问题标题】:Why does flex-box work with a div, but not a table?为什么 flex-box 可以与 div 一起使用,但不能与 table 一起使用?
【发布时间】:2017-05-16 05:55:19
【问题描述】:

以下简单的 sn-p 会生成一个占用可用屏幕空间的网页,顶部是页眉,底部是页脚,主要内容占用尽可能多的空间(带点边框以便于查看):

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  flex-flow: column;
}

h1, small {
  flex: 0 1 auto;
}

div {
  flex: 1 1 auto;
  border: 1px dotted;
}
<!doctype html>
<html>
  <body>
    <h1>Some Header</h1>
    <div>Some Text</div>
    <small>Some Footer</small>
  </body>
</html>

如果我修改 CSS 和 HTML 以使用 table 代替 div,它不会扩展表格以占用可用空间:

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  flex-flow: column;
}

h1, small {
  flex: 0 1 auto;
}

table {
  flex: 1 1 auto;
  border: 1px dotted;
}
<!doctype html>
<html>
  <body>
    <h1>Some Header</h1>
    <table><tr><td>Some Content</td></tr></table>
    <small>Some Footer</small>
  </body>
</html>

为什么第一个版本(div)可以工作,而第二个版本(table)不行?有没有办法修复第二个示例,使表格扩展并占用所有可用空间(不引入滚动条)?

一些注意事项:我的表格将有一行标题(均等宽)和几行(均等宽/高)。我知道可以使用一堆 divs 和更多 CSS 重新创建一个表格,但是沿着这条路线走下去感觉就像把婴儿和洗澡水一起扔掉(此外,我不会问这个问题并了解是否我只是绕过它)。此外,我在这里无法使用 JavaScript(而且看起来有点矫枉过正)。

我知道的 CSS/HTML 足以让自己陷入困境,但还不足以让自己摆脱困境......

编辑: aavrug 建议将 display: flex 用于 table 使得表格可以正确扩展以填充该区域,但是当我向表格添加多行/列时,它们不会更长的平均分布。我想保留table的单元格均匀分布。

【问题讨论】:

  • 因为表格有一个默认样式display: table;,只需用display: flex;覆盖它就可以了。
  • 嗯,这样做会导致我的表格单元格分布不均匀。
  • 我想您还必须将表格行设置为 display:flex,因为 &lt;td&gt; 元素是 flex 父级的子级的子级。
  • @Cornstalks 那是因为您将其覆盖为不呈现为表格。只需在其中放置一个&lt;div&gt; 并在其上使用 flex。
  • @Dodekeract 这又回到了同样的问题 - 你如何让 flex'd div 内的表格成为 div 的 100% 高度?

标签: html css flexbox css-tables


【解决方案1】:

我认为问题在于the table box is placed inside a table wrapper box:

表格生成一个称为表格包装框的主体块框,其中包含表格框本身和任何标题框

因此,表格框不再是 flex 容器的子项,因此也不是 flex 项。弹性项目是表格包装盒,但您将flex 属性设置为table 元素,并且

不可继承属性的值用于表格框,而不是 表格包装盒

所以你的flex 被用在一个不是弹性项目的盒子上,因此被忽略了。

如果在表格包装盒上使用该属性可能会起作用,但无法选择它。即使可以,也不清楚是否应该根据它生成的表格布局而不是根据它参与的 Flexbox 布局来调整大小。

解决方法很简单:

  1. 将表格放在一个包装器中,这将是弹性项目
  2. 使用弹性布局根据需要调整弹性项目的大小
  3. 将表格从流中取出,并给它相对于弹性项目的确定长度

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}
body {
  display: flex;
  flex-flow: column;
}
h1, small {
  flex: 0 1 auto;
}
div {
  position: relative;
  flex: 1 1 0; /* Chrome needs non-auto flex-basis */
  overflow: auto;
}
table {
  position: absolute;
  height: 100%;
  width: 100%;
  left: 0;
  top: 0;
  table-layout: fixed;
  border-collapse: collapse;
}
td {
  border: 1px dotted;
  text-align: center;
}
<h1>Some Header</h1>
<div>
  <table><tr>
    <td>This</td>
    <td>is</td>
    <td>equidistributed.</td>
  </tr><tr>
    <td>This</td>
    <td>is also</td>
    <td>equidistributed.</td>
  </tr></table>
</div>
<small>Some Footer</small>

只是为了好玩,避免添加包装器的一种巧妙方法是将表格样式设置为块,并将自动插入的 tbody 设置为表格。

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}
body {
  display: flex;
  flex-flow: column;
}
h1, small {
  flex: 0 1 auto;
}
table {
  display: block;
  position: relative;
  flex: 1 1 0;
}
tbody {
  display: table;
  position: absolute;
  height: 100%;
  width: 100%;
  left: 0;
  top: 0;
  table-layout: fixed;
  border-collapse: collapse;
  box-sizing: border-box;
}
td {
  border: 1px dotted;
  text-align: center;
}
<h1>Some Header</h1>
<table><tr>
  <td>This</td>
  <td>is</td>
  <td>equidistributed.</td>
</tr><tr>
  <td>This</td>
  <td>is also</td>
  <td>equidistributed.</td>
</tr></table>
<small>Some Footer</small>

【讨论】:

【解决方案2】:

html table 元素在 flex 容器中保留其 display 属性:

display: table

因此,它不接受 flex 属性。

但是,只需使用 display: block display: flex 覆盖该规则,布局就可以正常工作。

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}
body {
  display: flex;
  flex-flow: column;
}
h1,
small {
  flex: 0 1 auto;
}
table {
  display: flex;
  flex: 1 1 auto;
}
tbody {
  display: flex;
  width: 100%;
}
tr {
  display: flex;
  width: 100%;
}
td {
  flex: 1;
  border: 1px solid red;
}
<h1>Some Header</h1>
<table>
  <tr>
    <td>Some Content</td>
    <td>Some Content</td>
    <td>Some Content</td>
    <td>Some Content</td>
    <td>Some Content</td>
  </tr>
</table>
<small>Some Footer</small>

【讨论】:

  • 没有一个头脑正常的人会像这样将表格更改为块框。是一张桌子!并且表格有非常具体的布局规则,除非作者特别想以非表格方式布置它们 - 及其内容 - 否则应该保留这些规则。
  • @BoltClock,我的目标是解决为什么表格元素不能在弹性容器中工作。我把哲学问题留给你。我只是一个简单的人:-)
  • @Michael_B:当然可以,但从不建议更改要显示的表格:阻止!这就像建议使用表格进行布局的相反;)
  • @Oriol:我不知道。再想一想 table { display: block } 真正发生的所有事情是在 inside 表格中创建了一个匿名表格框,因此表格布局不会被破坏,但这确实意味着该表格不适用于该匿名表格框,因此您最终得到的只是一个无法设置样式的默认表格框。如果表只有一个 tbody...
【解决方案3】:

第二个示例(&lt;table&gt; 作为 flex 项)应该像 Firefox 87 中的第一个示例 (bug 1674302) 一样正确拉伸。

【讨论】:

    【解决方案4】:

    有一件事,你应该使用 vw 和 vh 单位来表示高度和宽度,大多数浏览器都不支持它们,但它们确实擅长它们可以做的事情。此外,对于表格问题,您从未将其指定为宽度,因此您只会得到一个适合文本的单元格。

    添加诸如“宽度:75vw;”之类的内容到表格样式会有所帮助(您可以使用 %s 作为宽度)

    【讨论】:

    • 如果您使用 flex,您不会倾向于使用 width: 属性,而是会使用 flex: ...,这就是他所做的。
    • 啊,我明白了。但是,我不明白他为什么不这样做并使 tr 标签的宽度相同。
    • 相反,所有现代浏览器都支持vwvh
    猜你喜欢
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-31
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多