HTML表格单元格是否可以通过CSS重新排列?

15

我想知道是否可能仅使用CSS重新排列HTML表格单元格。

例如,这个能否实现

------------------------------------------------
|             A            |    B    |    C    |
------------------------------------------------

应显示为:

------------------------------------------------
|    C    |             A            |    B    |
------------------------------------------------

或者甚至是这个:

-------------------------
|           A           |
-------------------------
|     B     |     C     |
-------------------------

这是否只能通过CSS实现,还是需要修改HTML节点呢? 编辑:一些人想知道为什么需要这样做,所以这是我面临的现实问题:
我想显示一个用户报告的问题列表:
------------------------------------------------------------------------------
| Problem description (A) | Reporting user (B) | Link to affected entity (C) |
------------------------------------------------------------------------------

我想评估各种布局。第一种布局变体会强调报告用户,第二种则会强调文本描述。

我没有改变结构的任何问题,实际上我已经改变了,但是当我在编写代码时,我想知道是否可能使用CSS。 (只是出于好奇)


仅在现代浏览器中运行的东西可接受吗? - thirtydot
你为什么要用CSS来做这个?如果你想改变表格的意义/结构,应该修改HTML。 - BoltClock
@BoltClock:我不想改变意思,只是想改变布局。 - Daniel Rikowski
对于一个表格来说,其布局往往传达着意义。 - DA.
@DA:没错,但大多数可视化表示都是如此 :) - Daniel Rikowski
显示剩余4条评论
5个回答

4
你可以这样做,但并不是最好的选择(请参考其他答案)。以下是我的示例:

*{margin:0; padding:0}
.type-a .b {width: 50%; float:left;}
.type-a .a {width:100%; float:left;}
.type-a .c {width: 50%; float:left;}

.type-b .b {width: 25%; float:left;}
.type-b .a {width: 50%; float:right;}
.type-b .c {width: 25%; float:left;}
<table class="type-a" width="100%" border="0" cellspacing="0" cellpadding="0">
  <tr>
    <td class="a" style="background-color:#060">A</td>
    <td class="b" style="background-color:#006">B</td>
    <td class="c" style="background-color:#600">C</td>
  </tr>
  <tr>
    <td class="a" style="background-color:#060">A</td>
    <td class="b" style="background-color:#006">B</td>
    <td class="c" style="background-color:#600">C</td>
  </tr>
</table>

<br />
<br />
<table class="type-b" width="100%" border="0" cellspacing="0" cellpadding="0">
  <tr>
    <td class="a" style="background-color:#060">A</td>
    <td class="b" style="background-color:#006">B</td>
    <td class="c" style="background-color:#600">C</td>
  </tr>
  <tr>
    <td class="a" style="background-color:#060">A</td>
    <td class="b" style="background-color:#006">B</td>
    <td class="c" style="background-color:#600">C</td>
  </tr>
</table>

在JSFiddle上查看


2
从技术上讲,当您为display:table-cell的元素定义float:left|right;时,您完全将它们从表格布局管理中移除。例如,如果您想使行中的单元格具有相同的高度,则您的方法将无法实现。请参见:http://jsfiddle.net/ye8Qa/1/ - c-smile
@c-smile,完全正确。我确实说过这不是最好的做法,你的评论也是另一个原因。虽然问题可能暗示了,但问题并没有说明必须遵守表格布局管理。 - Cubed Eye
我的眼睛!!!这一定是最糟糕的颜色选择。 - Ahmad

3
十多年后,我们可以使用现代CSS来拼凑出一个解决方案。
一开始我想使用网格布局,但我觉得这不适用于这种情况。相反,我将通过使用嵌套的flexbox来“黑客”这个表格。
首先让我们看一下表格的DOM树:
table
  ├ thead (optional)
  │ ⋮
  ├ tfoot (optional)
  │ ⋮
  └ tbody (one or many)
    ├ tr
    │ ├ td/th
    │ ⋮
    │ └ td/th
    ⋮
    └ tr
      ├ td/th
      ⋮
      └ td/th

theadtfoot 标签内的结构与 tbody 相同。
我们将使用三级嵌套的 flexbox 布局来替换表格布局:
一个包含垂直(即列)弹性盒子的 table 元素。通常只有一个子元素(tbody),但有时还会有两个或三个子元素(除了 tbody,还有 theadtfoot),甚至可能有更多的子元素(允许多个连续的 tbody 元素)。
  • 包含垂直(即列)弹性盒子的表格部分元素。子元素是表格行。
    • 包含水平(即行)弹性盒子的表格行元素。
    • 为了加分,我们可以让此布局 换行
      • 可使用 order 进行重新排序并使用 flex 调整大小的表格单元格(这是 flex-growflex-shrinkflex-basis 的简写)。
      • 所有列的宽度必须事先确定,无法自动设置列宽。
看看这段代码(并运行片段以查看结果)。

table.flextable {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
table.flextable > thead,
table.flextable > tfoot,
table.flextable > tbody {
    display: flex;
    flex-direction: column;
    gap: 1px;
}
table.flextable > * > tr {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 1px;
}

/* Column A has twice the width. Column C comes before the other two. */
table.flextable.type-a .a {flex: 2 2 0; order: 1;}
table.flextable.type-a .b {flex: 1 1 0; order: 1;}
table.flextable.type-a .c {flex: 1 1 0; order: 0;}

/* These dimensions cannot add up to 100% due to gap/margin/padding/border. */
/* Thus, we are using calc() to disregard that extra space. */
table.flextable.type-b .a {flex: 1 1 calc(100% - 1px - 2em);}
table.flextable.type-b .b {flex: 1 1 calc(50% - 1px - 2em);}
table.flextable.type-b .c {flex: 1 1 calc(50% - 1px - 2em);}

/* Stylistic rules, not relevant to the layout. */
.a {background-color: #CFC;}
.b {background-color: #CCF;}
.c {background-color: #FCC;}
td, th {padding: 0.5em 1em;}
td::before {content: "<td>";}
th::before {content: "<th>";}
td::after {content: "</td>";}
th::after {content: "</th>";}
<h2>Plain table</h2>
<table>
  <thead>
    <tr>
      <th class="a">A</th> <th class="b">B</th> <th class="c">C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="a">a</td> <td class="b">b</td> <td class="c">c</td>
    </tr>
    <tr>
      <td class="a">a</td> <td class="b">b</td> <td class="c">c</td>
    </tr>
  </tbody>
</table>

<h2>Reordering the table cells</h2>

<table class="flextable type-a">
  <thead>
    <tr>
      <th class="a">A</th> <th class="b">B</th> <th class="c">C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="a">a</td> <td class="b">b</td> <td class="c">c</td>
    </tr>
    <tr>
      <td class="a">a</td> <td class="b">b</td> <td class="c">c</td>
    </tr>
  </tbody>
</table>

<h2>Wrapping one table row into two rows</h2>

<table class="flextable type-b">
  <thead>
    <tr>
      <th class="a">A</th> <th class="b">B</th> <th class="c">C</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="a">a</td> <td class="b">b</td> <td class="c">c</td>
    </tr>
    <tr>
      <td class="a">a</td> <td class="b">b</td> <td class="c">c</td>
    </tr>
  </tbody>
</table>

这个答案为了教育价值而保持简短。以下问题留给读者作为练习:
  • tfoot 应该在 tbody 之前,但浏览器应该在所有 tbody 元素之后显示它。这可以通过使用 order 属性在此 flexbox 中进行 hack。
  • 具有 colspan 的单元格将会带来一些挑战,但可以通过添加更多的 CSS 规则来解决。
  • 具有 rowspan 的单元格肯定会破坏布局。除非对 HTML 进行其他更改,否则很难修复它。
  • border-collapse 在此 hack 中不受支持,因为我们没有使用 CSS 表格模型
  • <caption> 在此代码中未实现,但可能很容易支持。
  • <colgroup><col> 元素在此处不受支持。
  • 我们可以通过巧妙地使用 :nth-child() 来避免向每个表格单元格添加类。

2
当前在CSS中没有这样的功能。
CSS3将以某种形式提供flexbox模型(目前在W3C积极开发),它应该允许您做想做的事情。

0

你可以用比较取巧的方法来实现,比如可以尝试使用float属性。

但对于你提供的最后一个设计示例,我认为你应该尝试调整宽度(上面那个应该是width:100%;,其他两个应该是50%)。


0

你可以使用适当的标记和一点CSS来完成所有三个功能。http://jsfiddle.net/jalbertbowdenii/xvBhF/

公平警告:我不确定AT(辅助技术)能否像这样处理表格数据,但无论如何,如果你要公开发布,那么你可能需要研究一下。我相信有一种方法可以使用所有仅适用于表格样式的HTML属性。


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