The <tr> Element
Technical Summary
tr represents one row in a table and contains the row's td and th cells. Its rowIndex is measured against the table's rows, while sectionRowIndex is measured against its parent's rows collection. The parent is usually a row group, but it can be the table itself when the context allows it.
When source markup puts a tr directly under table, the parser inserts an implicit tbody into the DOM. This is a difference between source text and the parsed DOM. Browser observations and WPT results are recorded separately from the role mapping defined by HTML-AAM.
Definition, context, and content model
| Item | Specification summary | Condition / scope |
|---|---|---|
| Meaning | A row of cells in a table | The cells carry their own data or heading meaning through td or th |
| Context | Child of thead, tbody, or tfoot; it may also be a child of table under specific conditions | The table must have no tbody child; the order relative to other children also matters. HTML markup has an additional syntax restriction |
| Content model | Zero or more td, th, and script-supporting elements | An empty row is permitted by this content model |
| Content category | Belongs to no specific category | Defined separately as part of the table model |
| Content attributes | Global attributes | No tr-specific content attributes are defined |
| End tag | May be omitted under conditions | When immediately followed by another tr, or when the parent has no more content |
| DOM interface | HTMLTableRowElement | Provides row positions, a cell collection, and cell insertion and deletion |
The HTML Standard's content model has a conditional case for a tr child of table, but its HTML syntax conformance rules say that a table must not contain a tr directly. For source markup that does so, the parser inserts a tbody start tag. New markup is easier to read when its row groups are explicit.
Row groups and parser construction
| Element | Role in the table | Relationship to rows |
|---|---|---|
thead | Heading part of the table | Contains heading rows |
tbody | Main body of the table | Multiple row groups can separate parts of the data |
tfoot | Summary part of the table | Contains summary rows |
<table>
<thead><tr><th>Item</th><th>Value</th></tr></thead>
<tbody><tr><th>Total</th><td>3</td></tr></tbody>
</table>
Each tr in this example has a row group as its parent. A cell with rowspan="0" spans the remaining rows in the same row group, so group boundaries affect the table model when a table has multiple tbody elements.
HTMLTableRowElement and row APIs
| Member | Value or behavior | Scope / boundary |
|---|---|---|
rowIndex | Position in the table's rows collection | Zero-based; -1 when the row is not associated with a table |
sectionRowIndex | Position in the parent table or row group's rows collection | Zero-based; -1 without a matching parent |
cells | An HTMLCollection of the row's child td and th elements | Cells inside a nested table are not included |
insertCell(index) | Creates and inserts a new td | Default is -1; an out-of-range index throws IndexSizeError |
deleteCell(index) | Removes the td or th at the given position | -1 removes the last cell; an out-of-range index throws IndexSizeError |
const row = document.querySelector("tbody tr");
row.rowIndex; // Position in the whole table
row.sectionRowIndex; // Position in its parent tbody
row.cells; // This row's th and td elements
row.insertCell(-1); // Append a td
row.deleteCell(-1); // Remove the last cell
rowIndex is not a visual column position or a section-local number. When a table has several row groups, keep the whole-table and parent-group indexes separate. If a row is a direct child of a table, sectionRowIndex uses the table's rows collection. Also, insertCell() always creates a td.
Accessibility role
HTML-AAM maps the implicit role of tr to row. Exposure in a browser Accessibility tree, values in a platform API, and speech from an assistive technology are different measurements. The Implementation Evidence below records only the environments and scope actually observed.
Facts / Evidence
Key specification claims are mapped to their conditions and source locations. Implementation observations, WPT runs, and Accessibility role queries are recorded separately below.
| Type | Fact / claim | Condition / scope | Status | Evidence |
|---|---|---|---|---|
| SPEC | tr is a table row whose children are td, th, and script-supporting elements. | Element meaning, context, content model, global attributes, and end tag. | Reviewed | HTML Standard: the tr element |
| SPEC | rowIndex and sectionRowIndex use different rows collections. | Distinguish the whole table, the parent row group, a table that is the direct parent, and a row outside a table. | Reviewed | HTML Standard: the tr element |
| SPEC | cells contains child td and th elements; insertCell() creates a td. | Collection scope, insertion position, and index-range errors. | Reviewed | HTML Standard: the tr element |
| SPEC | The parser inserts an implied tbody start tag before a tr written directly under table. | Keep source markup distinct from the parsed DOM tree. | Reviewed | HTML Standard: restrictions on content models |
| AAM | HTML-AAM maps tr to the row role. | Keep the specification mapping separate from a browser Accessibility tree observation. | Specification reviewed | HTML-AAM: tr |
Evidence
- HTML Standard: The
trelement — meaning, context, content model, attributes, and row APIs - HTML Standard: The
tableelement — row groups and table child ordering - HTML Standard: Restrictions on content models — implied
tbodyfor atrwritten undertable - HTML Accessibility API Mappings:
tr— implicit row role and platform mappings - Web Platform Tests:
the-tr-element— row collections, indexes, and cell methods
Implementation Evidence
Specification requirements are kept separate from browser observations, WPT runs, and Accessibility role queries. Each result is limited to its recorded fixture, browser, and test selection.
| Type | Reproduced scope | Recorded conditions | Status |
|---|---|---|---|
| IMPL | HTMLTableRowElement, cells, rowIndex, sectionRowIndex, parser-implied tbody, and insertCell() / deleteCell() |
2026-10-11 JST / Chrome UA 155.0.0.0 (Windows NT 10.0 UA) / viewport 1280×720 / navigator.language=ja. Served build-config/yugien/research-results/tr-v1/ at loopback 127.0.0.1:4196; fixture checks passed 14/14. Confirmed that cells includes only direct td/th children and excludes nested-table cells; rowIndex counts across the table while sectionRowIndex restarts in each row group; the parser inserts tbody before a directly written tr; detached row indexes are -1; and insert/delete operations plus out-of-range IndexSizeError. One browser environment only. OS build and other browsers were not measured. |
Partial observation (Chrome 155 / fixture 14/14) |
| WPT | Selected WPTs for tr cell collections, cell insertion/deletion, rowIndex, and sectionRowIndex |
2026-10-11 JST / Chrome UA 155.0.0.0 / wpt.live. cells.html: 1/1 passed; deleteCell.html: 6/6 passed; insertCell.html: 7/7 passed; rowIndex.html: 12/12 passed; sectionRowIndex.html: 19/19 passed. Total: 45/45 passed. The upstream revision served by wpt.live could not be identified, so wptRevision is unrecorded. Unselected WPTs and other browsers were not run.Rerun (2026-10-11): Chrome 154.0.8037.98 / Windows build 26300. Ran 5 test files listed on this page: 45 checks passed, 0 failed, 0 timed out, and 0 did not run. Details: docs/atlas/wpt-results-2026-10-11.md. Other test files and browsers were not checked. This SHA applies only to the 2026-10-11 rerun; earlier WPT runs did not record their version.WPT version used: |
Partial run (test version recorded) |
| AAM | Native table, row group, row, column header, and data cell exposure through Chrome browser role queries | 2026-10-11 JST / Chrome UA 155.0.0.0 (Windows NT 10.0 UA) / viewport 1280×720 / navigator.language=ja. Queried the fixture table named Fruit prices today and observed 1 table, 5 rows, 4 row groups, 2 column headers, 0 row headers, and 8 data cells. Row names were Fruit / Price, Apples / $1.20, Pears / $1.45, Oranges / $0.80, and Items / 3. This is a browser role-query observation; full HTML-AAM coverage, platform APIs such as Windows UIA, and screen-reader speech were not measured. |
Partial observation (Chrome 155 browser role queries / one environment) |
A browser role/name query is not the same measurement as a platform Accessibility API or screen-reader speech. The observed layer and unmeasured scope stay separate.
Coverage / Open Issues
- ReviewedElement meaning, context and content model, row groups, main HTMLTableRowElement members, and the HTML-AAM role mapping
- OpenImplementation observations cover the selected fixture and one browser environment; all branches for multiple tables, section boundaries, and detached rows remain open
- OpenWPTs outside the selected set, other browser engines, and results against a pinned WPT revision
- OpenPlatform Accessibility APIs, Windows UI Automation, assistive-technology speech, other operating systems, and Expert-gap Review
This is initial coverage. Passing selected checks does not establish the same result for every HTML structure, browser, operating system, or assistive technology.
Related surfaces
For a beginner-friendly row example, see the Yugien tr page. For the section that groups body rows, see How to Use the tbody Element; for summary rows, see How to Use the tfoot Element. The full table model is covered by the table Topic; row-group rules and APIs by the tbody Topic and tfoot Topic; heading cells by th; data cells by td; and the table title by caption.