Skip to main content
HTML Validation

The “rowheader” role is unnecessary for element “th”.

About This HTML Issue

A <th> at the start of a data row already has the implicit role rowheader, so adding role="rowheader" to it changes nothing for screen readers.

The browser gives each <th> its ARIA role based on where the cell sits in the table. Header cells in the <thead>, or in a top row of headers, become columnheader. A header cell followed by <td> cells in the same row becomes rowheader. Add scope="row" when you want to state the direction outright: it marks the cell as the header for the rest of its row. The role attribute repeats information the table structure already carries and only makes the markup longer.

You'll get this warning for role="rowheader" on every <th>, whatever its position. If the cell actually heads a column, for example a <th> inside <thead>, the role is also incorrect: it replaces columnheader, so screen readers announce the cell as the label of a row.

Expect an error alongside the warning in most tables. A <th> can't carry any role attribute when its <table> has no role of its own, or has role="table", role="grid" or role="treegrid". Deleting role="rowheader" clears the warning and the error together.

Table plugins and page builders tend to put a role on every row and cell. The rowheader role is for tables built from generic elements such as <div> or <span>, which have no native way to mark a cell as a row header. On a <th>, remove the attribute and keep scope="row". If the same table also sets roles on its <tr>, <td> or <tbody> elements, the validator flags those too, so remove them in the same change.

Invalid example

<table>
  <thead>
    <tr>
      <th scope="col">Plan</th>
      <th scope="col">Monthly price</th>
      <th scope="col">Storage</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row" role="rowheader">Basic</th>
      <td>$5</td>
      <td>10 GB</td>
    </tr>
    <tr>
      <th scope="row" role="rowheader">Team</th>
      <td>$20</td>
      <td>100 GB</td>
    </tr>
  </tbody>
</table>

Valid example

<table>
  <thead>
    <tr>
      <th scope="col">Plan</th>
      <th scope="col">Monthly price</th>
      <th scope="col">Storage</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Basic</th>
      <td>$5</td>
      <td>10 GB</td>
    </tr>
    <tr>
      <th scope="row">Team</th>
      <td>$20</td>
      <td>100 GB</td>
    </tr>
  </tbody>
</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