在同一 HTML table 行中合并自动宽度、固定宽度和百分比宽度

Combine auto, fixed, and percentage width in same HTML table row

我想创建一个有 4 列的 table。 table 中的 2 列是标签,应该自动调整到最宽的元素。其他列之一是固定宽度,最后一列应填充剩余的 space。我第一次尝试创建这个 table 看起来像这样:

HTML

<table style="width:100%">
<tr>
  <td class="lbl">lbl:</td> <td class="fluidContent">Expandable Content 1</td>
  <td class="lbl">longer label:</td> <td class="fixedContent">Me Fixed</td>
</tr>
<tr>
  <td class="lbl">longer label:</td> <td class="fluidContent">Expandable Content 2</td>
  <td class="lbl">lbl:</td> <td class="fixedContent">Me Fixed</td>
</tr>
</table>

CSS

table {
  white-space: nowrap;
}

td {
  border: 1px solid orange;
}

.lbl {
  text-align: right;
  font-style: italic;
  width: auto;
}

.fluidContent {
  width: calc(100% - 120px);
}

.fixedContent {
  width: 120px;
}

https://jsfiddle.net/vf5p0m82/

不幸的是,此标记会生成具有流动宽度的标签列。 "lbl" class 单元格被视为具有 27% 的宽度,而 "fluidContent" 单元格的宽度为 46%。我想要的是 "lbl" 单元格尽可能小,同时仍然适合它们包含的最大字符串。

有什么方法可以简单地使用 tables 来完成我想要的,或者是时候使用新的 CSS3 flex-boxes 了吗?

编辑:一个解决方案

虽然为了清楚起见向这个问题添加了另一个示例,但我偶然发现了一个黑客来让它工作。如果你只是给自动调整大小的列宽度 1px 一切正常。看这里: https://jsfiddle.net/vf5p0m82/2/

是否有 established/canonical 方法来做到这一点或者就是这样?

可能有更正式的方法来执行此操作,但我发现有效的方法是将单元格宽度设置为 1px。内容大小会覆盖它,因此它只会折叠到内容大小。

.lbl {
  text-align: right;
  font-style: italic;
  width: 1px;
}

顺便说一下,table 格式似乎覆盖了 calc,但根据您的描述,您似乎不需要它。

查看实际效果:https://jsfiddle.net/vf5p0m82/1/

好的 flexbox 解决方案:https://jsfiddle.net/vf5p0m82/4/

HTML

<div class="fTbl">
  <div class="fluidWrapper">
    <div class="shrinkCol">
      <div class="lbl">lbl:</div>
      <div class="lbl">long lbl:</div>
    </div>
    <div class="stretchCol">
      <div class="fluidCell">Expand Content</div>
      <div class="fluidCell">Expand Content</div>
    </div>
  </div>
  <div class="fixedWrapper">
    <div class="shrinkCol">
      <div class="lbl">longer label:</div>
      <div class="lbl">lbl:</div>
    </div>
    <div class="shrinkCol">
      <div class="fixCell" style="width:100px;">Fixed</div>
      <div class="fixCell" style="width:100px;">Fixed</div>
    </div>
  </div>
</div>

CSS

.fTbl {
  border: solid magenta 2px;
  display: flex;
  flex-flow: row wrap;
  width: 100%;
  align-items: flex-start;
}

.fixedWrapper {
  display: flex;
  flex: 0 0 auto;
  flex-flow: row nowrap;
}

.fluidWrapper {
  display: flex;
  flex: 1 1 auto;
  flex-flow: row nowrap;
}

.shrinkCol {
  display: flex;
  flex: 0 0 auto;
  flex-flow: column nowrap;
}

.stretchCol {
  display: flex;
  flex: 1 1 auto;
  flex-flow: column nowrap;
}

.fluidCell {
  border: 2px solid orange;
  min-width: 140px;  
}

.fixCell {
  border: 2px solid orange;
}

.lbl {
  text-align: right;
  font-style: italic;
  border: 2px solid orange;
}

好的,下面是您通常如何使用这个 CSS:

  • 表格必须分成单独的列,每列逐行独立填写。
  • 如果不同列的行包含不同高度的项目,则必须明确赋予它们相同的高度。
  • Label/content 列对放置在 fixed/fluidWrapper 类 中,以便标签和内容(通常是文本框)包裹在一起,不会分开。
  • 不可能在 1 个 flex table 内有一个 "colspan" 而不将行彼此解耦并显式设置宽度。

我喜欢这种方法,因为它很容易让 flex 项目在垂直和水平方向上拉伸和压缩以填充页面,并且包装项目以响应窄屏幕非常简单。它也不需要像 table 那样的 hacky CSS。我发现 HTML table 有时会非常麻烦且不直观。

我不喜欢这种方法,因为 table 的一行不可能(或者可能很难)跨越多列。如果有更宽的项目,则必须将其放置在新容器中,因此不会与其上方的项目共享其标签宽度。然而,这些抱怨似乎源于 table 和 flex box 设计目标的内在差异,您必须简单地选择最适合给定布局的方法。

关于生成自动 table 列宽大约等于任何行中最宽列的列宽的搜索来到了这个问题。如果那是你想要做的,请在 CSS 中尝试 th,td {width: max-content;}。适合我。