[X]

The Table Body You Never Typed

parser and markup 1997 still works

Write a table with only tr rows and the parser slips a tbody between the table and every row.

In 2026: Still happens everywhere. The HTML parsing algorithm opens an implied tbody the moment a tr appears with no section element around it, so table.firstElementChild is a tbody you never wrote. It is why the CSS selector table > tr matches nothing, and why scripts must append new rows to the tbody rather than the table. thead and tfoot are the only sections the parser will not invent.

Where it came from: PPK (Peter-Paul Koch) documented the scripting consequence on quirksmode.org in the early 2000s. The insertion itself lives in the WHATWG parser in table insertion mode. MDN

<table id="t" border="1">
  <tr><td>a row with no tbody in the source</td></tr>
</table>
<script>
var t = document.getElementById('t');
document.write('<p>t.tBodies.length is <b>' + t.tBodies.length +
  '</b>, and the table first child is a &lt;' +
  t.firstElementChild.tagName.toLowerCase() + '&gt;.</p>');
</script>
sandboxed demo · breaks nothing but itselfrestart

More in parser and markup

all 4 in parser and markup › · the whole library ›