About This HTML Issue
The HTML specification defines a strict content model for tables. The <td> (table data) element represents a single cell containing data, and it can only appear as a child of a <tr> element. Table sectioning elements like <tbody>, <thead>, and <tfoot> may only contain <tr> elements as direct children — not <td> or <th> cells directly. When the validator encounters a <td> start tag inside a table body (or other section) without a wrapping <tr>, it reports this error.
This issue typically arises in a few common scenarios:
-
A missing
<tr>wrapper — the developer placed cells directly inside<tbody>or<table>without creating a row. -
A prematurely closed
<tr>— a typo or stray</tr>tag ended the row too early, leaving subsequent<td>elements orphaned. -
Dynamically generated HTML — template engines or JavaScript may produce table markup where
<tr>elements are accidentally omitted.
Why this matters
-
Standards compliance: The HTML living standard explicitly requires
<td>elements to be children of<tr>. Violating this produces invalid markup. -
Browser inconsistency: Browsers will attempt to error-correct by implicitly creating
<tr>elements, but different browsers may interpret the malformed structure differently, leading to unpredictable rendering. -
Accessibility: Screen readers and assistive technologies rely on correct table structure to navigate rows and columns. Missing
<tr>elements can confuse these tools, making the data harder or impossible to understand for users who depend on them. - Maintainability: Invalid table markup is harder to style with CSS and harder for other developers to understand and maintain.
Examples
Incorrect — <td> directly inside <tbody>
The <td> elements are children of <tbody> instead of being wrapped in a <tr>:
<table>
<tbody>
<td>Name</td>
<td>Age</td>
</tbody>
</table>
Correct — <td> wrapped in <tr>
Adding a <tr> element creates a valid table row:
<table>
<tbody>
<tr>
<td>Name</td>
<td>Age</td>
</tr>
</tbody>
</table>
Incorrect — prematurely closed <tr> leaves orphaned cells
Here the first </tr> closes the row too early, so the second <td> ends up directly inside <tbody>:
<table>
<tbody>
<tr>
<td>Cell 1</td>
</tr>
<td>Cell 2</td>
<td>Cell 3</td>
</tbody>
</table>
Correct — all cells placed inside proper rows
Either include all cells in one row, or create multiple rows as needed:
<table>
<tbody>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td>Cell 3</td>
</tr>
</tbody>
</table>
Or, if you intended two separate rows:
<table>
<tbody>
<tr>
<td>Cell 1</td>
</tr>
<tr>
<td>Cell 2</td>
<td>Cell 3</td>
</tr>
</tbody>
</table>
Incorrect — <td> directly inside <table> with no sections or rows
<table>
<td>Alpha</td>
<td>Beta</td>
</table>
Correct — minimal valid table structure
While <tbody> is optional (browsers add it implicitly), a <tr> is always required:
<table>
<tr>
<td>Alpha</td>
<td>Beta</td>
</tr>
</table>
To fix this error, inspect your table markup and ensure every <td> (and <th>) element is a direct child of a <tr>. Check for stray closing </tr> tags that might end rows prematurely, and verify that any dynamically generated table content produces <tr> wrappers around cell elements.
Find issues like this automatically
Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.