About This HTML Issue
An element with role="cell" has no ancestor with role="row", and no row claims it through aria-owns.
An ARIA table nests its roles in a fixed order: table, then an optional rowgroup, then row, then cell (or columnheader and rowheader). Screen readers use that structure to announce a cell's row and column and to move between cells. A cell outside any row has no position in the table, so it may be read as loose text or skipped.
The row doesn't have to be the cell's direct parent. Plain <div> or <span> wrappers between a role="row" element and its cells pass, so layout wrappers can stay. The error appears when no ancestor has the row role at all: cells placed straight inside role="table" or role="rowgroup", a row wrapper that only has a class, or a role="cell" used outside any table. When the cells can't sit inside the row in the DOM, give each one an id and list those ids in aria-owns on the row.
Newer versions of the validator word this message as an element with the “role” value “row”, with the same cause and fix.
For tabular data, a native <table> with <tr> and <td> gives you this structure without any role attributes.
Invalid example
The second row's wrapper has a class but no role="row":
<div role="table" aria-label="Team members">
<div role="row">
<div role="columnheader">Name</div>
<div role="columnheader">Role</div>
</div>
<div class="member">
<div role="cell">Alice</div>
<div role="cell">Designer</div>
</div>
</div>
Valid example
With role="row" on the wrapper, the cells belong to a row, even with an extra layout <div> in between:
<div role="table" aria-label="Team members">
<div role="row">
<div role="columnheader">Name</div>
<div role="columnheader">Role</div>
</div>
<div role="row">
<div class="row-inner">
<div role="cell">Alice</div>
<div role="cell">Designer</div>
</div>
</div>
</div>
Find issues like this automatically
Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.