# The element “h2” must not appear as a descendant of the “th” element.

> Canonical HTML version: https://rocketvalidator.com/html-validation/the-element-h2-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/)

The HTML specification defines a strict content model for the `th` element: it accepts flow content, but specifically excludes `header`, `footer`, sectioning content, and heading content (`h1`–`h6`). This restriction exists because `th` elements are themselves headers — they describe the data in their corresponding row or column. Placing a heading element inside a `th` creates a conflict in the document outline and semantic structure.

This matters for several reasons:

- **Accessibility:** Screen readers use headings to build a navigable document outline. Headings buried inside table header cells can confuse assistive technology, making it harder for users to understand the page structure and navigate between sections.
- **Document outline:** Heading elements define the hierarchical structure of a document's content. When headings appear inside table cells, they disrupt this hierarchy and create unexpected, often meaningless, sections in the outline.
- **Standards compliance:** Browsers may handle this invalid nesting inconsistently, and the W3C validator will flag it as an error.

A common reason developers place headings in `th` cells is to achieve a specific visual style — larger or bolder text. The correct approach is to use CSS to style the `th` content directly, keeping the markup clean and valid.

## How to Fix It

1. **Remove the heading element** from inside the `th`.
2. **Move the heading above the table** if you need a title or section heading for the table.
3. **Use CSS** to style the `th` text if you need a particular visual appearance.
4. **Use the `caption` element** if you want to provide a visible title that is semantically associated with the table.

## Examples

### ❌ Incorrect: Heading inside a `th` element

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

This triggers the validation error because `h2` elements are not permitted as descendants of `th`.

### ✅ Correct: Plain text inside `th`, heading moved outside

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

### ✅ Correct: Using `caption` for 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>
```

The `caption` element is the semantically appropriate way to give a table a title. It is announced by screen readers in context with the table, providing a better experience than a heading placed before the table.

### ✅ Correct: Styling `th` with CSS for visual emphasis

If the heading was added purely for visual effect, use CSS instead:

```html
<style>
  .prominent-header th {
    font-size: 1.5em;
    font-weight: bold;
    color: #333;
  }
</style>

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

This gives you full control over the appearance of header cells without breaking the document structure or introducing validation errors. Remember: `th` elements are already semantically headers, so there's no need to wrap their content in heading elements.
