Sobre este problema HTML
A especificação ARIA define uma hierarquia de propriedade rigorosa para roles relacionados com tabelas. Um columnheader representa uma célula de cabeçalho para uma coluna, análogo a um elemento <th> em HTML nativo. Para que as tecnologias assistivas como leitores de ecrã anunciem corretamente os cabeçalhos de coluna e os associem com as células de dados abaixo deles, o columnheader deve existir dentro de um contexto de row. A estrutura necessária é:
-
Um elemento com
role="table",role="grid", ourole="treegrid"serve como contentor. -
Dentro dele, elementos com
role="rowgroup"(opcional) ourole="row"organizam as linhas. -
Cada elemento
role="row"contém um ou mais elementos comrole="columnheader",role="rowheader", ourole="cell".
Quando um elemento role="columnheader" é colocado diretamente dentro de um contentor role="table" ou role="grid" — ou qualquer outro elemento que não seja role="row" — o validador levanta este erro. Sem o invólucro row, os leitores de ecrã não conseguem navegar pela estrutura da tabela adequadamente. Os utilizadores que dependem de tecnologia assistiva podem ouvir conteúdo desconexo ou perder completamente os cabeçalhos de coluna, tornando a tabela de dados inutilizável.
A melhor prática, sempre que possível, é usar elementos de tabela HTML nativos (<table>, <thead>, <tr>, <th>, <td>). Estes carregam roles ARIA implícitos e estabelecem automaticamente as relações de propriedade corretas, eliminando toda esta categoria de erros. Use apenas roles de tabela ARIA quando genuinamente não puder usar marcação de tabela nativa — por exemplo, ao construir um widget de grelha personalizado com elementos não-tabela por razões de layout.
Exemplos
Incorreto: columnheader não dentro de um row
Neste exemplo, os elementos columnheader são filhos diretos do contentor table, sem um invólucro role="row":
<div role="table" aria-label="Employees">
<div role="columnheader">Name</div>
<div role="columnheader">Department</div>
<div role="row">
<div role="cell">Alice</div>
<div role="cell">Engineering</div>
</div>
</div>
Correto: columnheader dentro de um row
Envolver os cabeçalhos de coluna num elemento com role="row" corrige o problema:
<div role="table" aria-label="Employees">
<div role="row">
<div role="columnheader">Name</div>
<div role="columnheader">Department</div>
</div>
<div role="row">
<div role="cell">Alice</div>
<div role="cell">Engineering</div>
</div>
</div>
Correto: usar rowgroup para estrutura adicional
Pode opcionalmente usar role="rowgroup" para separar cabeçalhos das linhas do corpo, similar a <thead> e <tbody>. Os elementos columnheader devem ainda estar dentro de um row:
<div role="table" aria-label="Employees">
<div role="rowgroup">
<div role="row">
<div role="columnheader">Name</div>
<div role="columnheader">Department</div>
</div>
</div>
<div role="rowgroup">
<div role="row">
<div role="cell">Alice</div>
<div role="cell">Engineering</div>
</div>
</div>
</div>
Melhor prática: usar elementos de tabela nativos
As tabelas HTML nativas têm semântica incorporada que torna os roles ARIA desnecessários. Um <th> dentro de um <tr> já se comporta como um columnheader dentro de um row:
<table>
<thead>
<tr>
<th>Name</th>
<th>Department</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>Engineering</td>
</tr>
</tbody>
</table>
Esta abordagem é mais simples, mais robusta entre navegadores e tecnologias assistivas, e evita o risco de uso incorreto do ARIA. Reserve os roles de tabela ARIA para situações onde a marcação de tabela nativa não é uma opção.
Encontre problemas como este automaticamente
O Rocket Validator analisa milhares de páginas em segundos, detetando problemas HTML em todo o seu site.