# Bad value “rowgroup” for attribute “role” on element “header”.

> Canonical HTML version: https://rocketvalidator.com/html-validation/bad-value-rowgroup-for-attribute-role-on-element-header
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The `rowgroup` role represents a group of rows within a tabular structure — similar to what `<thead>`, `<tbody>`, or `<tfoot>` provide in a native HTML `<table>`. According to the ARIA specification, the `rowgroup` role should be used on elements that serve as structural containers for rows within a `grid`, `table`, or `treegrid`. A `<header>` element is not appropriate for this role because it carries its own strong semantic meaning (typically `banner` or a sectioning header), and overriding it with `role="rowgroup"` creates a conflict that the W3C validator flags.

This matters for several reasons. First, assistive technologies rely on correct role assignments to convey the structure of a page. When a `<header>` element is given `role="rowgroup"`, screen readers receive contradictory signals about what the element represents, which can confuse users. Second, the HTML specification restricts which ARIA roles can be applied to certain elements — the `<header>` element does not allow `rowgroup` as a valid role override.

To fix this issue, you have two main options:

1. **Replace the `<header>` element with a `<div>`** — since `<div>` has no implicit ARIA role, it freely accepts `role="rowgroup"`.
2. **Use native HTML table elements** — replace the custom ARIA table structure with `<table>`, `<thead>`, `<tbody>`, `<tr>`, `<th>`, and `<td>`, which provide the correct semantics without requiring any ARIA roles.

## Examples

### ❌ Incorrect: `role="rowgroup"` on a `<header>` element

```html
<div role="table" aria-label="Quarterly Sales">
  <header role="rowgroup">
    <div role="row">
      <span role="columnheader">Quarter</span>
      <span role="columnheader">Revenue</span>
    </div>
  </header>
  <div role="rowgroup">
    <div role="row">
      <span role="cell">Q1</span>
      <span role="cell">$1.2M</span>
    </div>
  </div>
</div>
```

The validator reports **Bad value "rowgroup" for attribute "role" on element "header"** because `<header>` cannot accept the `rowgroup` role.

### ✅ Fix option 1: Use a `<div>` instead of `<header>`

```html
<div role="table" aria-label="Quarterly Sales">
  <div role="rowgroup">
    <div role="row">
      <span role="columnheader">Quarter</span>
      <span role="columnheader">Revenue</span>
    </div>
  </div>
  <div role="rowgroup">
    <div role="row">
      <span role="cell">Q1</span>
      <span role="cell">$1.2M</span>
    </div>
  </div>
</div>
```

A `<div>` is semantically neutral, so `role="rowgroup"` is perfectly valid on it.

### ✅ Fix option 2: Use native HTML table elements

```html
<table>
  <caption>Quarterly Sales</caption>
  <thead>
    <tr>
      <th>Quarter</th>
      <th>Revenue</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Q1</td>
      <td>$1.2M</td>
    </tr>
  </tbody>
</table>
```

Native table elements like `<thead>` and `<tbody>` implicitly carry the `rowgroup` role, so no ARIA attributes are needed at all. This approach is generally preferred because it provides the best accessibility support out of the box and results in cleaner, more maintainable markup. Only use ARIA table roles when you cannot use native HTML tables (for example, when building a custom grid layout that requires non-table CSS).
