Skip to main content
HTML Validation

The element “h1”–“h6” must not appear as a descendant of the “th” element.

About This HTML Issue

A th element can't contain a heading, from h1 to h6, at any depth. Put the text straight in the th, style it with CSS, or title the table with a caption or a heading before it.

The HTML standard defines the content of a th as flow content with no header, footer, sectioning content or heading content (h1 to h6 and hgroup) among its descendants. The rule applies at any depth, so a heading wrapped in a div inside the th still triggers this error. The message names the heading level the validator found, and the fix is the same for every level. A td doesn't have this restriction: headings are allowed in data cells.

A th is already a header. Screen readers announce it when they read the cells of its row or column, so a heading inside it adds nothing to the table. It does add an entry to the page's heading outline, and users who move through the page by headings land inside the table as if a new section started there.

Headings usually end up in header cells to make the text bigger or bolder. Browsers already show th text in bold, and CSS can change the size, weight or letter case.

How to fix it

  1. Remove the heading element and keep its text directly inside the th.
  2. Style the th with CSS if the header cells need a particular look.
  3. Use a caption if the heading was meant as a title for the whole table. A caption is tied to the table, and screen readers announce it with it.
  4. Put a heading before the table if the table needs an entry in the page's outline, at a level that fits the surrounding headings.

Examples

❌ Invalid: heading inside a th

<table>
  <tr>
    <th><h2>Product</h2></th>
    <th><h2>Price</h2></th>
  </tr>
  <tr>
    <td>Widget</td>
    <td>$25</td>
  </tr>
</table>

Each h2 is a descendant of a th, which the th content model doesn't allow.

✅ Valid: plain text in the th, styled with CSS

<table class="price-table">
  <tr>
    <th>Product</th>
    <th>Price</th>
  </tr>
  <tr>
    <td>Widget</td>
    <td>$25</td>
  </tr>
</table>
.price-table th {
  font-size: 1.2em;
  text-transform: uppercase;
}

✅ Valid: a caption as the table title

<table>
  <caption>Product pricing</caption>
  <tr>
    <th>Product</th>
    <th>Price</th>
  </tr>
  <tr>
    <td>Widget</td>
    <td>$25</td>
  </tr>
</table>

✅ Valid: a heading before the table

<h2>Product pricing</h2>
<table>
  <tr>
    <th>Product</th>
    <th>Price</th>
  </tr>
  <tr>
    <td>Widget</td>
    <td>$25</td>
  </tr>
</table>

Find issues like this automatically

Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.

Help us improve our guides

Was this guide helpful?
🌍 Trusted by teams worldwide

Validate at scale.
Ship accessible websites, faster.

Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.

Scheduled Reports
API Access
Open Source Standards
€5 / week

1K Weekly

1,000 monthly checks. Cancel anytime.

Get 1K Weekly →

Join teams across 40+ countries