Können wir mehrere <tbody> in derselben <table> haben?

594

Können wir mehrere <tbody>Tags in einem haben <table>? Wenn ja, in welchen Szenarien sollten wir dann mehrere <tbody>Tags verwenden?

Jitendra Vyas
quelle

Antworten:

710

Ja, Sie können sie verwenden. Ich verwende sie beispielsweise, um Datengruppen wie folgt einfacher zu formatieren:

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>

Hier können Sie ein Beispiel anzeigen . Es funktioniert nur in neueren Browsern, aber das unterstütze ich in meiner aktuellen Anwendung. Sie können die Gruppierung für JavaScript usw. verwenden. Hauptsache, es ist eine bequeme Möglichkeit, die Zeilen visuell zu gruppieren, um die Daten besser lesbar zu machen . Es gibt natürlich auch andere Verwendungszwecke, aber soweit zutreffend, ist dieses für mich das häufigste.

Nick Craver
quelle
6
ok danke für die tolle antwort. Ist es wichtig, einen tbodyoder mehrere Bildschirmleser zu verwenden ?
Jitendra Vyas
1
@ metal-gear-solid - Nach meiner Erfahrung gehen sie gut damit um, zB: als ob sie eins wären <tbody>. Wenn Sie anfangen, Tabellen zu verschachteln , führt dies normalerweise zu echten Navigationsproblemen für einen Bildschirmleser.
Nick Craver
10
@metal: Nein, es gibt einen semantischen Unterschied - mehrere <tbody>Elemente beschreiben separate Gruppen in der Tabelle, wie in der Antwort erläutert wurde. Außerdem sollte ich hinzufügen, dass es im Allgemeinen besser ist, Zellen auf Hintergründe auszurichten, daher sollte das CSS beispielsweisetbody:nth-child(odd) td { background: #f5f5f5; }
DisgruntledGoat
4
Was ist die Definition von "neueren Browsern"?
Tim Down
8
@ TimDown - als ich "neuere Browser" sagte, bezog es sich nur auf die CSS- :nth-child()Verwendung für die verknüpfte Demonstration, das Multiple <tbody>funktioniert in jedem Browser.
Nick Craver
298

Ja. Aus der DTD

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

Es werden also eine oder mehrere erwartet. Dann heißt es weiter

Verwenden Sie mehrere tbody-Abschnitte, wenn Regeln zwischen Gruppen von Tabellenzeilen benötigt werden.

Martin Smith
quelle
12
Ab der HTML5-Spezifikation ändert sich dies geringfügig, aber das grundlegende "Ja, mehrere tbodyElemente sind in Ordnung" bleibt erhalten. Insbesondere können Sie jetzt das eine tfootElement nach dem anderen setzen, tbodywenn Sie möchten . (Sie haben den DTD-Aspekt ordentlich umgangen indem sie sagen, dass sie keine zur Verfügung stellen .) :-)
TJ Crowder
5
Danke für diese Antwort. Das Referenzieren von Spezifikationen ist die Antwort Nr. 1 in meinem Buch.
KernelCurry
1
Es werden also ein oder mehrere erwartet. Dies ist falsch, es kann eine Menge sein, <tr>also könnte es auch Null sein (dh ein tbody oder ein tr bedeutet, dass es nur ein tr und kein tbody sein könnte.)
Alexis Wilke
@AlexisWilke Dies gilt gemäß den Spezifikationen: Das TBODY-Start-Tag ist immer erforderlich, außer wenn die Tabelle nur einen Tabellenkörper und keine Tischkopf- oder Fußabschnitte enthält
Gecko IT
14

Das Problem von Martin Joiner wird durch ein Missverständnis des <caption>Tags verursacht.

Das <caption>Tag definiert eine Tabellenbeschriftung.

Das <caption>Tag muss das erste untergeordnete <table>Element des Tags sein.

Sie können nur eine Beschriftung pro Tabelle angeben.

Beachten Sie außerdem, dass das scopeAttribut auf einem <th>Element und nicht auf einem <tr>Element platziert werden sollte.

Der richtige Weg, eine Multi-Header-Multi-Tbody-Tabelle zu schreiben, wäre ungefähr so:

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

John Slegers
quelle
Das captionTag sollte dem öffnenden tableTag folgen . developer.mozilla.org/en-US/docs/Web/HTML/Element/table
Cypher
Du hast recht. Ich habe die Dokumente irgendwie falsch interpretiert. Ich habe den Fehler behoben.
John Slegers
Spec empfiehlt die Verwendung scope="rowgroup"(anstelle von col) der tbodyHeader. Siehe Beispiel .
CletusW
7

Ja. Ich benutze sie, um den relevanten Teil einer Tabelle, z. B. einen Kurs, dynamisch auszublenden / aufzudecken. Nämlich.

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

Es kann eine Schaltfläche bereitgestellt werden, mit der Sie zwischen allen oder nur dem aktuellen Tag wechseln können, indem Sie tbodies bearbeiten, ohne viele Zeilen einzeln zu verarbeiten.

CPslashM
quelle
4

BEARBEITEN: Das captionTag gehört zur Tabelle und sollte daher nur einmal existieren. Ordnen Sie nicht captionjedem tbodyElement ein zu, wie ich es getan habe:

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

SCHLECHTES BEISPIEL OBEN: NICHT KOPIEREN

Das obige Beispiel wird nicht wie erwartet gerendert, da ein solches Schreiben auf ein Missverständnis des captionTags hinweist . Sie würden viele CSS-Hacks benötigen, um es korrekt zu rendern, da Sie gegen Standards verstoßen würden.

Ich habe nach W3Cs-Standards für das captionTag gesucht , konnte jedoch keine explizite Regel finden, die besagt, dass es nur ein captionElement pro Tabelle geben muss, aber das ist tatsächlich der Fall.

Martin Joiner
quelle
3

Wenn Sie ein HTML-Dokument mit mehreren <tbody>Tags über den HTML-Validator von W3C mit einem HTML5-DOCTYPE ausführen, wird es außerdem erfolgreich validiert.

Bern
quelle
2

Ich habe eine JSFiddle erstellt, in der ich zwei verschachtelte ng-Wiederholungen mit Tabellen und die übergeordnete ng-Wiederholung für tbody habe. Wenn Sie eine Zeile in der Tabelle untersuchen, sehen Sie, dass es sechs tbody-Elemente gibt, dh die übergeordnete Ebene.

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>

(Randnotiz: Dies füllt das DOM aus, wenn Sie viele Daten auf beiden Ebenen haben. Daher arbeite ich an einer Anweisung zum Abrufen und Ersetzen von Daten, dh Hinzufügen zu DOM beim Klicken auf übergeordnetes Element und Entfernen, wenn auf ein anderes oder dasselbe übergeordnete Element geklickt wird Um das Verhalten zu erhalten, das Sie auf Prisjakt.nu finden , scrollen Sie zu den aufgelisteten Computern und klicken Sie auf die Zeile (nicht auf die Links). Wenn Sie dies tun und Elemente überprüfen, sehen Sie, dass ein tr hinzugefügt wird und dann entfernt, wenn das übergeordnete Element erneut angeklickt wird.)

Pixic
quelle