HTML / Element / Initial coverage

The <tbody> Element

Status: Initial coverage Scope: HTML Living Standard Specification checked: 2026-10-17

Technical Summary

tbody is a child of table that groups the table's body rows. The HTML Standard treats tbody, thead, and tfoot as row groups. A row-group boundary is part of the table model and can affect cell-header relationships.

When the HTML parser encounters a tr directly inside table, it inserts an implicit tbody. The HTMLTableSectionElement interface exposes rows, insertRow(), and deleteRow() for working with rows in a section.

Definition, context, and content model

Basic definition of the tbody element
ItemSpecificationConditions and scope
MeaningA row group for the table bodyGroups body rows separately from heading and footer sections
ContextA child of tableSubject to the parent content model and ordering rules for caption, colgroup, thead, table body, and tfoot
Content modelZero or more tr elements and script-supporting elementsAn empty tbody is permitted by the content model
Start and end tagsMay be omitted under specific HTML syntax conditionsThe start tag can be omitted when the first content is a tr and it is not immediately preceded by a tbody, thead, or tfoot whose end tag was omitted. The end tag can be omitted before another tbody or a tfoot, or when the parent has no more content.
DOM interfaceHTMLTableSectionElementthead and tfoot use the same interface
Element-specific attributesNoneGlobal attributes are allowed

The table content model allows the body to be represented by zero or more tbody elements, or by one or more tr elements. When a tr token appears directly inside a table insertion mode, however, the HTML parser inserts a tbody in the DOM. Source conformance and the parser's DOM construction and recovery rules are separate.

Row groups and the table model

A row group is a unit of rows in the table grid. A cell cannot occupy slots in more than one row group. Therefore, rowspan="0" spans the remaining rows in the cell's own row group and does not continue into the next tbody.

Common row groups
ElementTypical purposeTable-model category
theadContains the column-heading sectionRow group
tbodyContains the table's body rowsRow group; may occur more than once
tfootContains footer rows such as totalsRow group

Do not infer a DOM row group from visual styling alone. Check the actual parent element and table model. The distinction also matters to the scope of th scope="rowgroup" and to the structure exposed to assistive technology.

DOM built by the parser

<table id="items">
  <tr><td>Apples</td></tr>
</table>

// DOM built by the HTML parser
table#items
└─ tbody  (inserted implicitly)
   └─ tr
      └─ td

When tr appears in the “in table” insertion mode, the parser inserts a tbody with no attributes and reprocesses the token. In the “in table body” insertion mode, a td or th appearing directly is a parse error; the parser inserts a tr with no attributes and reprocesses the cell token. These are parser-recovery behaviors, not authoring patterns to rely on.

HTMLTableSectionElement APIs

Common row APIs on tbody and table
MemberReturn value or behaviorRange and boundary
tbody.rowsAn HTMLCollection of the section's direct tr childrenA live collection that reflects row insertion and removal
table.tBodiesAn HTMLCollection of the table's child tbody elementsDoes not include thead, tfoot, or tbody elements in a nested table
tbody.insertRow(index)Creates a tr and inserts it into the section-1 appends; an out-of-range index throws IndexSizeError
tbody.deleteRow(index)Removes the selected tr from the section-1 removes the last row; empty-section and index boundaries follow the method's index rules
const table = document.querySelector("table");
const body = table.tBodies[0];
body.rows.length;       // rows in this tbody
body.insertRow(-1);     // append a row to this tbody
body.deleteRow(-1);     // remove its last row

tbody.rows returns rows in that section. table.rows is a collection for the whole table. The names are similar, but their scopes differ.

Accessibility mapping

HTML-AAM maps native tbody to the WAI-ARIA rowgroup role. This exposes a structural grouping within a table; it is not a visible heading string. Record the browser, operating system, and table structure when observing the browser Accessibility tree or a platform API.

Facts and evidence

Specification claims and implementation measurements are recorded separately. A browser role query is not itself the normative HTML-AAM mapping or a platform Accessibility API measurement.

Primary facts and source locations for tbody
TypeFact or claimConditions and scopeStatusEvidence
SPECtbody is a child of table; its content model allows zero or more tr and script-supporting elements.Includes table-child ordering, tag omission, and global attributes.Specification checkedHTML Standard: the tbody element
SPECA cell cannot span slots from multiple row groups; rowspan="0" covers the remaining rows in the same row group.Table grid, row-group boundary, and cell span.Specification checkedHTML Standard: forming a table
SPECThe parser inserts an implicit tbody before a tr token in a table. A direct td/th in a table body triggers an implicit tr and token reprocessing.Distinguishes parser recovery from conforming authoring markup.Specification checkedHTML Standard: in table / in table body
SPECHTML-AAM maps tbody to the rowgroup role.Distinguishes the normative mapping from individual browser Accessibility trees and platform API observations.Specification checkedHTML-AAM: tbody

Evidence

  1. HTML Standard: The tbody element — context, content model, tag omission, and section APIs
  2. HTML Standard: Forming a table — row groups, cell slots, and row-span boundaries
  3. HTML Standard: Table parsing modes — implied section and row insertion
  4. HTML Accessibility API Mappings: tbody — rowgroup role and platform mappings
  5. Web Platform Tests: the-tbody-element — section row collection and row methods
  6. Web Platform Tests: rowspan-0.html — row-span behavior at a row-group boundary

Implementation Evidence

Specification requirements are recorded separately from browser observations, WPT runs, and Accessibility role queries. Each result applies only to its stated fixture, browser, and test selection.

Implementation evidence register for tbody
TypeChecked behaviorConditionsStatus
IMPL HTMLTableSectionElement, tbody.rows / table.tBodies, insertRow() / deleteRow(), createTBody(), parser-inserted tbody / tr, and the rowspan=0 row-group boundary 2026-10-17 JST / Chrome UA 155.0.0.0 (Windows NT 10.0 UA) / viewport 1280×720 / navigator.language=ja. Served build-config/yugien/research-results/tbody-v1/ at loopback 127.0.0.1:4197; fixture checks passed 13/13. Confirmed the section interface and live row collection, the scope of table.tBodies, parser-inserted sections and rows, row insertion/deletion and boundary errors, empty-section deleteRow(-1), createTBody(), and the rowspan group boundary. One Chrome environment only; other browsers, OS build, and platform APIs were not measured. Partial observation (Chrome 155 / fixture 13/13)
WPT Selected WPTs for tbody.rows, insertRow() / deleteRow(), and the rowspan=0 row-group boundary 2026-10-17 JST / Chrome UA 155.0.0.0 / wpt.live. rows.html: 1/1 passed; insertRow.html: 6/6 passed; deleteRow.html: 6/6 passed; rowspan-0.html: 2/2 passed. Total: 15/15 passed. The exact upstream revision served by wpt.live could not be pinned. Unselected tests and other browsers were not run.

The test version used was not recorded. The linked test may change, so this result cannot be repeated with certainty against the same version.

Selected tests only (wpt.live revision not pinned)
AAM Native table, row group, row, column header, row header, and data cell exposure through Chrome browser role queries 2026-10-17 JST / Chrome UA 155.0.0.0 (Windows NT 10.0 UA) / viewport 1280×720 / navigator.language=ja. Queried the fixture table named Stock by group and observed 1 table, 4 row groups (thead, two tbody sections, and tfoot), 6 rows, 2 column headers, 5 row headers, and 5 cells. This is a browser role-query observation; Windows UI Automation and screen-reader speech were not measured. Partial observation (Chrome 155 browser role query / one environment)

A browser role/name query is not the same measurement as a platform Accessibility API or screen-reader speech. The tested layer and unmeasured scope are reported separately.

Coverage and open issues

  • Specification checkedContent model, table ordering, row groups, table parser, HTMLTableSectionElement, and HTML-AAM mapping
  • OpenImplementation evidence covers one selected fixture and browser environment; parser recovery branches and varied table structures remain untested
  • OpenWPT evidence covers selected files. The exact upstream revision served by wpt.live and other browsers were not confirmed
  • OpenPlatform Accessibility APIs, Windows UI Automation, assistive-technology speech, other operating systems, and Expert-gap Review

This Topic has initial coverage. Passing selected checks does not show that every HTML structure, browser, operating system, or assistive technology behaves the same way.

Related surfaces

For a beginner-friendly example, see How to Use the tbody Element in Yugien. The table Topic covers the table model; the header row group is covered in the thead Topic; summary row groups are covered in the tfoot Topic; tr covers rows and indexes; and th and td cover headers and data cells.