Skip to main content
Validación HTML

An element with “role=cell” must be contained in, or owned by, an element with “role=row”.

Acerca de este problema HTML

The ARIA specification defines a strict ownership hierarchy for table-related roles. A role="cell" element must be “owned by” an element with role="row", meaning it must either be a direct child of that element or be associated with it via the aria-owns attribute. This mirrors how native HTML tables work: a <td> element must live inside a <tr> element. When you use ARIA roles to build custom table structures from non-table elements like <div> or <span>, you are responsible for maintaining this same hierarchy manually.

The expected nesting order for an ARIA table is:

  1. role="table" — the outermost container
  2. role="rowgroup" (optional) — groups rows together, like <thead>, <tbody>, or <tfoot>
  3. role="row" — a single row of cells
  4. role="cell" or role="columnheader" / role="rowheader" — individual cells

When a role="cell" element is placed directly inside a role="table" or any other container that isn’t role="row", screen readers lose the ability to announce row and column positions. Users who rely on table navigation shortcuts (such as moving between cells with arrow keys) will find the table unusable. This is not just a validation concern — it directly impacts whether people can access your content.

This issue commonly arises when developers add intermediate wrapper elements for styling purposes and accidentally break the required parent-child relationship, or when they forget to assign role="row" to a container element.

How to Fix

Ensure every element with role="cell" is a direct child of an element with role="row". If you have wrapper elements between the row and cell for layout or styling, either remove them, move the role assignments, or use aria-owns on the row element to explicitly claim ownership of the cells.

Examples

Incorrect — Cell Without a Row Parent

This triggers the validation error because role="cell" elements are direct children of the role="table" container, with no role="row" in between.

<div role="table">
  <div role="cell">Name</div>
  <div role="cell">Email</div>
</div>

Incorrect — Intermediate Wrapper Breaking Ownership

Here, a styling wrapper sits between the row and its cells. Since the <div> without a role is not a role="row", the cells are not properly owned.

<div role="table">
  <div role="row">
    <div class="cell-wrapper">
      <div role="cell">Row 1, Cell 1</div>
      <div role="cell">Row 1, Cell 2</div>
    </div>
  </div>
</div>

Correct — Cells Directly Inside Rows

Each role="cell" is a direct child of a role="row" element, forming a valid ARIA table structure.

<div role="table" aria-label="Team members">
  <div role="row">
    <div role="columnheader">Name</div>
    <div role="columnheader">Email</div>
  </div>
  <div role="row">
    <div role="cell">Alice</div>
    <div role="cell">alice@example.com</div>
  </div>
  <div role="row">
    <div role="cell">Bob</div>
    <div role="cell">bob@example.com</div>
  </div>
</div>

Correct — Using Rowgroups

You can optionally group rows with role="rowgroup", similar to <thead> and <tbody>. The cells still must be direct children of their rows.

<div role="table" aria-label="Quarterly results">
  <div role="rowgroup">
    <div role="row">
      <div role="columnheader">Quarter</div>
      <div role="columnheader">Revenue</div>
    </div>
  </div>
  <div role="rowgroup">
    <div role="row">
      <div role="cell">Q1</div>
      <div role="cell">$10,000</div>
    </div>
    <div role="row">
      <div role="cell">Q2</div>
      <div role="cell">$12,500</div>
    </div>
  </div>
</div>

Correct — Using Native HTML Instead

If your content is genuinely tabular data, consider using native HTML table elements instead of ARIA roles. Native tables have built-in semantics and require no additional role attributes.

<table>
  <tr>
    <th>Name</th>
    <th>Email</th>
  </tr>
  <tr>
    <td>Alice</td>
    <td>alice@example.com</td>
  </tr>
</table>

Native HTML tables are always preferable when they suit your use case. The first rule of ARIA is: if you can use a native HTML element that already has the semantics you need, use it instead of adding ARIA roles to a generic element.

Encuentra problemas como este automáticamente

Rocket Validator escanea miles de páginas en segundos, detectando problemas de HTML en todo tu sitio web.

Ayúdanos a mejorar nuestras guías

¿Te ha sido útil esta guía?

¿Listo para validar tus sitios?
Inicia tu prueba gratuita hoy.