Chúng ta có thể có nhiều <tbody> trong cùng một <bảng> không?


594

Chúng ta có thể có nhiều <tbody>thẻ giống nhau <table>không? Nếu có thì trong trường hợp nào chúng ta nên sử dụng nhiều <tbody>thẻ?

Câu trả lời:


710

Có, bạn có thể sử dụng chúng, ví dụ tôi sử dụng chúng để dễ dàng tạo kiểu các nhóm dữ liệu hơn, như thế này:

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>

Bạn có thể xem một ví dụ ở đây . Nó sẽ chỉ hoạt động trong các trình duyệt mới hơn, nhưng đó là những gì tôi đang hỗ trợ trong ứng dụng hiện tại của mình, bạn có thể sử dụng nhóm cho JavaScript, v.v. Điều chính là cách thuận tiện để nhóm các hàng một cách trực quan để dữ liệu dễ đọc hơn nhiều . Tất nhiên có những cách sử dụng khác, nhưng theo như các ví dụ áp dụng, thì đây là cách sử dụng phổ biến nhất đối với tôi.


6
ok cảm ơn vì câu trả lời tuyệt vời Là vấn đề với trình đọc màn hình, một tbodyhoặc nhiều?
Jitendra Vyas

1
@ metal-gear-solid - Theo kinh nghiệm của tôi, họ xử lý chúng tốt, ví dụ: như thể chúng là một <tbody>. Khi bạn bắt đầu lồng các bảng, đó là những gì thường gây ra vấn đề điều hướng thực sự cho trình đọc màn hình.
Nick Craver

10
@metal: không, có một sự khác biệt về ngữ nghĩa - nhiều <tbody>yếu tố mô tả các nhóm riêng biệt trong bảng, như đã được giải thích trong câu trả lời. Ngoài ra, tôi nên thêm rằng nói chung là tốt hơn để nhắm mục tiêu các ô cho nền, vì vậy, CSS sẽ là, ví dụ,tbody:nth-child(odd) td { background: #f5f5f5; }
DisgruntledGoat

4
Định nghĩa của "trình duyệt mới hơn" là gì?
Tim Xuống

8
@TimDown - khi tôi nói "trình duyệt mới hơn", nó chỉ đề cập đến việc :nth-child()sử dụng CSS cho trình diễn được liên kết, nhiều <tbody>trình duyệt sẽ hoạt động trong bất kỳ trình duyệt nào.
Nick Craver

298

Đúng. Từ ĐTDĐ

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

Vì vậy, nó mong đợi một hoặc nhiều. Sau đó nó tiếp tục nói

Sử dụng nhiều phần tbody khi cần quy tắc giữa các nhóm hàng bảng.


12
Tính đến spec HTML5, những thay đổi này một chút, nhưng cơ bản "có, nhiều tbodyyếu tố này là tốt) còn lại. Cụ thể, bây giờ bạn đang cho phép để đưa một tfootyếu tố sau sự tbodynếu bạn thích . (Họ gọn gàng phụ bước khía cạnh DTD bằng cách nói rằng họ không cung cấp một .) :-)
TJ Crowder

5
Cảm ơn phản hồi này. Thông số kỹ thuật tham khảo là câu trả lời số 1 trong cuốn sách của tôi.
KernelCurry

1
Vì vậy, nó mong đợi một hoặc nhiều. Điều này là sai, nó có thể là một tập hợp <tr>vì vậy nó cũng có thể là số không (nghĩa là một tbody hoặc tr có nghĩa là nó chỉ có thể là một tr và không có tbody.)
Alexis Wilke

@AlexisWilke điều này đúng theo thông số kỹ thuật: Thẻ bắt đầu
Gecko IT


14

Vấn đề của Martin Joiner là do sự hiểu lầm về <caption>thẻ.

Các <caption>thẻ định nghĩa một chú thích bảng.

Các <caption>thẻ phải là đứa con đầu lòng của <table>thẻ.

Bạn chỉ có thể chỉ định một chú thích cho mỗi bảng.

Ngoài ra, lưu ý rằng scopethuộc tính nên được đặt trên một <th>phần tử chứ không phải trên một <tr>phần tử.

Cách thích hợp để viết một bảng nhiều người nhiều tiêu đề sẽ giống như thế này:

<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>


Các captionthẻ nên theo việc mở tablethẻ. developer.mozilla.org/en-US/docs/Web/HTML/Euity/table
Cypher

Bạn đúng. Tôi bằng cách nào đó giải thích sai các tài liệu. Tôi đã sửa lỗi.
John Slegers

Spec khuyên bạn nên sử dụng scope="rowgroup"(thay vì col) cho các tbodytiêu đề. Xem ví dụ .
CletusW

7

Đúng. Tôi sử dụng chúng để ẩn / tiết lộ phần có liên quan của bảng, ví dụ như một khóa học. Viz.

<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>

Một nút có thể được cung cấp để chuyển đổi giữa mọi thứ hoặc chỉ ngày hiện tại bằng cách thao tác các chuỗi mà không xử lý nhiều hàng riêng lẻ.


4

EDIT: captionThẻ thuộc về bảng và do đó chỉ nên tồn tại một lần. Không liên kết a captionvới từng tbodyyếu tố như tôi đã làm:

<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>

BAD VÍ DỤ TRÊN: KHÔNG SAO CHÉP

Ví dụ trên không hiển thị như bạn mong đợi vì viết như thế này cho thấy sự hiểu lầm về captionthẻ. Bạn sẽ cần rất nhiều hack CSS để làm cho nó hiển thị chính xác bởi vì bạn sẽ đi ngược lại các tiêu chuẩn.

Tôi đã tìm kiếm các tiêu chuẩn W3C trên captionthẻ nhưng không thể tìm thấy quy tắc rõ ràng rằng các trạng thái phải chỉ có một captionyếu tố trên mỗi bảng nhưng thực tế là như vậy.



2

Tôi đã tạo một JSFiddle trong đó tôi có hai lần lặp ng lồng nhau với các bảng và cha-ng lặp lại trên tbody. Nếu bạn kiểm tra bất kỳ hàng nào trong bảng, bạn sẽ thấy có sáu phần tử tbody, tức là cấp độ cha.

HTML

<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>

(Lưu ý bên lề: Điều này sẽ lấp đầy DOM nếu bạn có nhiều dữ liệu ở cả hai cấp độ, do đó tôi đang thực hiện một lệnh để tìm nạp dữ liệu và thay thế, tức là thêm vào DOM khi nhấp vào cha mẹ và xóa khi nhấp vào khác hoặc cùng cha mẹ một lần nữa. Để có được loại hành vi bạn tìm thấy trên Prisjakt.nu , nếu bạn cuộn xuống các máy tính được liệt kê và nhấp vào hàng (không phải các liên kết). Nếu bạn làm điều đó và kiểm tra các yếu tố bạn sẽ thấy rằng một tr được thêm vào và sau đó xóa nếu cha mẹ được nhấp lại hoặc khác.)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.