# An element with “role=rowgroup” must be contained in, or owned by, an element with the “role” value “treegrid”, “grid”, or “table”.

> Canonical HTML version: https://rocketvalidator.com/html-validation/an-element-with-role-rowgroup-must-be-contained-in-or-owned-by-an-element-with-the-role-value-treegrid-grid-or-table
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

An element with `role="rowgroup"` needs an ancestor with `role="table"`, `role="grid"`, or `role="treegrid"`, or one of those elements has to claim it through `aria-owns`.

A `rowgroup` groups the rows of a table, the way `<thead>`, `<tbody>` and `<tfoot>` do in a native `<table>`. It only means something inside the structure it divides. With no `table`, `grid` or `treegrid` above it, a screen reader has no table to announce, so it can't report the number of rows and columns or let people move from cell to cell with its table commands.

This often shows up in cards or comparison layouts built from `<div>` elements. The rows and cells inside carry ARIA roles, but the outer container has only a class for styling. Add `role="table"` to that container and give it a name with `aria-label` or `aria-labelledby`, so screen readers can say which table it is. Pick `grid` or `treegrid` only when the widget lets people move between cells with the arrow keys.

The table doesn't have to be the rowgroup's direct parent. The validator accepts plain wrapper elements in between, as long as some ancestor has one of the three roles. When the rowgroup can't sit inside the table in the DOM, give it an `id` and list that id in `aria-owns` on the table.

If the content isn't really tabular, such as a short list of features in a card, remove `role="rowgroup"`, `role="row"` and `role="cell"` together and use a list or plain text. If you remove only the rowgroup role, the validator reports each row instead. For real tabular data, a native `<table>` with `<tbody>`, `<tr>` and `<td>` gives you the same structure without any ARIA.

## Invalid example

The rows sit in a rowgroup, but the wrapper around it has no table role.

```html
<h2 id="specs-title">Technical details</h2>
<div class="specs">
  <div role="rowgroup">
    <div role="row">
      <span role="cell">Weight</span>
      <span role="cell">1.2 kg</span>
    </div>
    <div role="row">
      <span role="cell">Battery life</span>
      <span role="cell">18 hours</span>
    </div>
  </div>
</div>
```

## Valid example

With `role="table"` and a name on the wrapper, the rowgroup has a table to belong to.

```html
<h2 id="specs-title">Technical details</h2>
<div class="specs" role="table" aria-labelledby="specs-title">
  <div role="rowgroup">
    <div role="row">
      <span role="cell">Weight</span>
      <span role="cell">1.2 kg</span>
    </div>
    <div role="row">
      <span role="cell">Battery life</span>
      <span role="cell">18 hours</span>
    </div>
  </div>
</div>
```
