同一个<table>标签中能否有多个<tbody>标签?

646

在同一个 <table> 中可以有多个 <tbody> 标签吗?如果可以,那么应该在什么情况下使用多个 <tbody> 标签呢?


此外,如果您在 HTML5 DOCTYPE 上运行带有多个<tbody>标签的HTML文档通过W3C的HTML验证器,它将能够成功验证。 - Bern
7个回答

778

是的,你可以使用它们。例如,我使用它们来更轻松地为数据组添加样式,就像这样:

thead th { width: 100px; border-bottom: solid 1px #ddd; font-weight: bold; }
tbody:nth-child(odd) { background: #f5f5f5;  border: solid 1px #ddd; }
tbody:nth-child(even) { background: #e5e5e5;  border: solid 1px #ddd; }
<table>
    <thead>
        <tr><th>Customer</th><th>Order</th><th>Month</th></tr>
    </thead>
    <tbody>
        <tr><td>Customer 1</td><td>#1</td><td>January</td></tr>
        <tr><td>Customer 1</td><td>#2</td><td>April</td></tr>
        <tr><td>Customer 1</td><td>#3</td><td>March</td></tr>
    </tbody>
    <tbody>
        <tr><td>Customer 2</td><td>#1</td><td>January</td></tr>
        <tr><td>Customer 2</td><td>#2</td><td>April</td></tr>
        <tr><td>Customer 2</td><td>#3</td><td>March</td></tr>
    </tbody>
    <tbody>
        <tr><td>Customer 3</td><td>#1</td><td>January</td></tr>
        <tr><td>Customer 3</td><td>#2</td><td>April</td></tr>
        <tr><td>Customer 3</td><td>#3</td><td>March</td></tr>
    </tbody>
</table>

您可以在此处查看示例。这只适用于更新的浏览器,但这是我当前应用程序支持的,您可以使用组合功能进行 JavaScript 等等。主要问题是这是一种方便的方式来直观地组合行,使数据更易读。当然还有其他用途,但就可适用的示例而言,对我来说这是最常见的一种。


6
好的,谢谢您的问题。对于屏幕阅读器而言,一个 tbody 还是多个 tbody 是否重要呢? - Jitendra Vyas
11
@metal: 不是的,这里存在语义上的差别 - 多个<tbody>元素描述了表格中不同的分组,正如答案所解释的那样。此外,我应该补充说明的是,通常最好为单元格设置背景颜色,因此CSS应该是这样的:tbody:nth-child(odd) td { background: #f5f5f5; } - DisgruntledGoat
5
“新版浏览器”的定义是什么? - Tim Down
8
当我提到“新一点的浏览器”时,只是指CSS中:nth-child()用法的链接示例,多个<tbody>在任何浏览器中都可以工作。请注意,这里只做翻译,不包括解释或其他内容。 - Nick Craver
1
这是一个非常简单的想法,但当您需要某种层次结构,深度为3-7级时该怎么办?您不应该将TBODY元素嵌入到彼此中,对吧? - mshthn
显示剩余5条评论

310

是的,来自DTD

<!ELEMENT table
     (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>

所以它期望一个或多个。然后继续说:

当需要在表格行组之间使用规则时,请使用多个tbody部分。


13
根据HTML5规范,这有些改变,但基本的“是的,多个 tbody 元素是可以的”仍然有效。具体来说,如果你愿意的话,现在允许在 tbody 后面放置一个 tfoot 元素。通过声明不提供DTD方面的内容,它们巧妙地规避了DTD方面的问题。 :-) - T.J. Crowder

50
根据规范的示例,可以这样做:w3-struct-tables。 引用如下: 表格行可以使用THEAD、TFOOT和TBODY元素分组为表头、表尾和一个或多个表体部分。

17
马丁·乔伊纳的问题是由于对<caption>标签的误解引起的。 <caption>标签定义了表格标题。 <caption>标签必须是<table>标签的第一个子元素。
每个表格只能指定一个标题。
另外,请注意,scope属性应该放在<th>元素上而不是<tr>元素上。
编写多个表头和多个tbody的正确方式应该像这样:
<table id="dinner_table">
    <caption>This is the only correct place to put a caption.</caption>
    <tbody>
        <tr class="header">
            <th colspan="2" scope="col">First Half of Table (British Dinner)</th>
        </tr>
        <tr>
            <th scope="row">1</th>
            <td>Fish</td>
        </tr>
        <tr>
            <th scope="row">2</th>
            <td>Chips</td>
        </tr>
        <tr>
            <th scope="row">3</th>
            <td>Peas</td>
        </tr>
        <tr>
            <th scope="row">4</th>
            <td>Gravy</td>
        </tr>
    </tbody>
    <tbody>
        <tr class="header">
            <th colspan="2" scope="col">Second Half of Table (Italian Dinner)</th>
        </tr>
        <tr>
            <th scope="row">5</th>
            <td>Pizza</td>
        </tr>
        <tr>
            <th scope="row">6</th>
            <td>Salad</td>
        </tr>
        <tr>
            <th scope="row">7</th>
            <td>Oil</td>
        </tr>
        <tr>
            <th scope="row">8</th>
            <td>Bread</td>
        </tr>
    </tbody>
</table>


规范建议在 tbody 表头中使用 scope="rowgroup"(而不是 col)。请参见示例 - CletusW

8

是的,我使用它们来动态隐藏/显示表格的相关部分,例如课程。即:

<table>
  <tbody id="day1" style="display:none">
    <tr><td>session1</td><tr>
    <tr><td>session2</td><tr>
  </tbody>
  <tbody id="day2">
    <tr><td>session3</td><tr>
    <tr><td>session4</td><tr>
  </tbody>
  <tbody id="day3" style="display:none">
    <tr><td>session5</td><tr>
    <tr><td>session6</td><tr>
  </tbody>
</table>

一个按钮可以被提供,通过操作表格主体(tbodies)来切换“全部数据”或“仅当前日期”,而无需单独处理多行数据。

2
我创建了一个JSFiddle,其中有两个嵌套的ng-repeats和表格,以及在tbody上的父级ng-repeat。如果您检查表中的任何一行,您将看到有六个tbody元素,即父级别。
<div>
        <table class="table table-hover table-condensed table-striped">
            <thead>
                <tr>
                    <th>Store ID</th>
                    <th>Name</th>
                    <th>Address</th>
                    <th>City</th>
                    <th>Cost</th>
                    <th>Sales</th>
                    <th>Revenue</th>
                    <th>Employees</th>
                    <th>Employees H-sum</th>
                </tr>
            </thead>
            <tbody data-ng-repeat="storedata in storeDataModel.storedata">
                <tr id="storedata.store.storeId" class="clickableRow" title="Click to toggle collapse/expand day summaries for this store." data-ng-click="selectTableRow($index, storedata.store.storeId)">
                    <td>{{storedata.store.storeId}}</td>
                    <td>{{storedata.store.storeName}}</td>
                    <td>{{storedata.store.storeAddress}}</td>
                    <td>{{storedata.store.storeCity}}</td>
                    <td>{{storedata.data.costTotal}}</td>
                    <td>{{storedata.data.salesTotal}}</td>
                    <td>{{storedata.data.revenueTotal}}</td>
                    <td>{{storedata.data.averageEmployees}}</td>
                    <td>{{storedata.data.averageEmployeesHours}}</td>
                </tr>
                <tr data-ng-show="dayDataCollapse[$index]">
                    <td colspan="2">&nbsp;</td>
                    <td colspan="7">
                        <div>
                            <div class="pull-right">
                                <table class="table table-hover table-condensed table-striped">
                                    <thead>
                                        <tr>
                                            <th></th>
                                            <th>Date [YYYY-MM-dd]</th>
                                            <th>Cost</th>
                                            <th>Sales</th>
                                            <th>Revenue</th>
                                            <th>Employees</th>
                                            <th>Employees H-sum</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr data-ng-repeat="dayData in storeDataModel.storedata[$index].data.dayData">
                                            <td class="pullright">
                                                <button type="btn btn-small" title="Click to show transactions for this specific day..." data-ng-click=""><i class="icon-list"></i>
                                                </button>
                                            </td>
                                            <td>{{dayData.date}}</td>
                                            <td>{{dayData.cost}}</td>
                                            <td>{{dayData.sales}}</td>
                                            <td>{{dayData.revenue}}</td>
                                            <td>{{dayData.employees}}</td>
                                            <td>{{dayData.employeesHoursSum}}</td>
                                        </tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>

(旁注: 如果两个级别上有大量数据,这将填充DOM,因此我正在开发一个指令来获取数据并替换,即在单击父级时添加到DOM中,当单击另一个或同一父级时删除。 要获得Prisjakt.nu上的行为方式,请向下滚动到列出的计算机并单击行(而不是链接)。 如果您这样做并检查元素,则会看到添加了一个tr,然后在再次单击父项或其他父项时将其删除。)

2

编辑:<caption> 标签属于表格,因此只能存在一次。不要像我一样将一个 <caption> 与每个 <tbody> 元素相关联:

<table>
    <caption>First Half of Table (British Dinner)</caption>
    <tbody>
        <tr><th>1</th><td>Fish</td></tr>
        <tr><th>2</th><td>Chips</td></tr>
        <tr><th>3</th><td>Pease</td></tr>
        <tr><th>4</th><td>Gravy</td></tr>
    </tbody>
    <caption>Second Half of Table (Italian Dinner)</caption>
    <tbody>
        <tr><th>5</th><td>Pizza</td></tr>
        <tr><th>6</th><td>Salad</td></tr>
        <tr><th>7</th><td>Oil</td></tr>
        <tr><th>8</th><td>Bread</td></tr>
    </tbody>
</table>

上述错误示例:不要复制

上述示例不能按照您的期望呈现,因为这样编写表明对caption标签的理解有误。如果您这样做,需要大量使用CSS技巧才能使其正确呈现,因为您将违反标准。

我搜索了W3C关于caption标签的标准,但没有找到明确规定每个表格只能有一个caption元素的规则,但事实上确实如此。


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