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

> Canonical HTML version: https://rocketvalidator.com/html-validation/the-element-h1-to-h6-must-not-appear-as-a-descendant-of-the-th-element
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

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`

```html
<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

```html
<table class="price-table">
  <tr>
    <th>Product</th>
    <th>Price</th>
  </tr>
  <tr>
    <td>Widget</td>
    <td>$25</td>
  </tr>
</table>
```

```css
.price-table th {
  font-size: 1.2em;
  text-transform: uppercase;
}
```

### ✅ Valid: a `caption` as the table title

```html
<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

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