Possiamo avere più <tbody> nello stesso <table>?


594

Possiamo avere più <tbody>tag nello stesso <table>? Se sì, in quali scenari dovremmo usare più <tbody>tag?

Risposte:


710

Sì, puoi usarli, ad esempio li uso per definire più facilmente gruppi di dati, come questo:

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>

Puoi vedere un esempio qui . Funzionerà solo nei browser più recenti, ma è quello che sto supportando nella mia attuale applicazione, puoi utilizzare il raggruppamento per JavaScript ecc. La cosa principale è che è un modo conveniente per raggruppare visivamente le righe per rendere i dati molto più leggibili . Ci sono altri usi ovviamente, ma per quanto riguarda gli esempi applicabili, questo è il più comune per me.


6
ok grazie per un'ottima risposta. È importante per lo screen reader, uno tbodyo più?
Jitendra Vyas,

1
@ metal-gear-solid - Nella mia esperienza li gestiscono bene, ad esempio: come se fossero uno <tbody>. Quando inizi a nidificare le tabelle, questo è ciò che di solito crea veri problemi di navigazione per uno screen reader.
Nick Craver

10
@metal: no, c'è una differenza semantica - più <tbody>elementi descrivono gruppi separati nella tabella, come è stato spiegato nella risposta. Inoltre, dovrei aggiungere che in genere è meglio indirizzare le celle per gli sfondi, quindi il CSS dovrebbe essere, ad esempio,tbody:nth-child(odd) td { background: #f5f5f5; }
DisgruntledGoat

4
Qual è la definizione di "browser più recenti"?
Tim Down

8
@TimDown - quando ho detto "browser più recenti" si riferiva solo :nth-child()all'uso CSS per la dimostrazione collegata, il multiplo <tbody>funzionerà in qualsiasi browser.
Nick Craver

298

Sì. Dal DTD

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

Quindi si aspetta uno o più. Quindi continua a dire

Usa più sezioni del corpo quando sono necessarie regole tra gruppi di righe della tabella.


12
A partire dalle specifiche HTML5, questo cambia leggermente, ma tbodyrimane fondamentale il "sì, più elementi vanno bene". In particolare, ora ti è permesso di mettere l'unico tfootelemento dopo il tbodyse ti piace . (Hanno abilmente spostato lateralmente l'aspetto DTD dicendo che non ne forniscono uno .) :-)
TJ Crowder,

5
Grazie per questa risposta Le specifiche di riferimento sono la risposta numero 1 nel mio libro.
KernelCurry,

1
Quindi si aspetta uno o più. Questo è sbagliato, potrebbe essere un insieme di <tr>quindi potrebbe anche essere zero (cioè un corpo o un tr significa che potrebbe essere solo un tr e nessun corpo.)
Alexis Wilke,

@AlexisWilke questo è vero secondo le specifiche: il tag di inizio TBODY è sempre richiesto tranne quando la tabella contiene solo un corpo di tabella e nessuna sezione di testa o piede della tabella
Gecko IT


14

Il problema di Martin Joiner è causato da un fraintendimento del <caption>tag.

Il <caption>tag definisce una didascalia della tabella.

Il <caption>tag deve essere il primo figlio del <table>tag.

È possibile specificare solo una didascalia per tabella.

Si noti inoltre che l' scopeattributo deve essere posizionato su un <th>elemento e non su un <tr>elemento.

Il modo corretto di scrivere una tabella multi-body multi-header sarebbe qualcosa del genere:

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


Il captiontag dovrebbe seguire il tabletag di apertura . developer.mozilla.org/en-US/docs/Web/HTML/Element/table
Cypher

Hai ragione. In qualche modo ho interpretato male i documenti. Ho corretto l'errore.
John Slegers,

Le specifiche consiglia di utilizzare scope="rowgroup"(anziché col) per le tbodyintestazioni. Vedi esempio .
CletusW,

7

Sì. Li uso per nascondere / svelare dinamicamente la parte rilevante di una tabella, ad esempio un corso. Cioè.

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

È possibile fornire un pulsante per alternare tra tutto o solo il giorno corrente manipolando i corpi senza elaborare molte righe singolarmente.


4

EDIT: il captiontag appartiene alla tabella e quindi dovrebbe esistere solo una volta. Non associare captiona ogni tbodyelemento come ho fatto io:

<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 ESEMPIO SOPRA: NON COPIARE

L'esempio sopra non viene visualizzato come previsto perché scrivere in questo modo indica un malinteso del captiontag. Avresti bisogno di un sacco di hack CSS per renderlo correttamente perché andresti contro gli standard.

Ho cercato gli standard W3C sul captiontag ma non sono riuscito a trovare una regola esplicita che affermi che ci deve essere solo un captionelemento per tabella, ma in realtà è il caso.



2

Ho creato un JSFiddle cui ho due ng-ripetizioni nidificate con tabelle e il gen ng-repeat sul corpo. Se ispezioni una riga nella tabella, vedrai che ci sono sei elementi del corpo, ovvero il livello principale.

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>

(Nota a margine: questo riempie il DOM se hai molti dati su entrambi i livelli, quindi sto quindi lavorando su una direttiva per recuperare i dati e sostituirli, vale a dire aggiungere in DOM quando si fa clic sul genitore e rimuovere quando si fa clic su un altro o stesso genitore di nuovo. Per ottenere il tipo di comportamento che trovi su Prisjakt.nu , se scorri verso il basso fino ai computer elencati e fai clic sulla riga (non sui collegamenti). Se lo fai e controlli gli elementi vedrai che viene aggiunto un tr e quindi rimosso se si fa di nuovo clic su parent o su un altro.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.