Sobre esta regra de acessibilidade
As tabelas de dados comunicam informação estruturada onde o significado de cada célula depende da sua posição relativa aos cabeçalhos de linha e coluna. Quando observa uma tabela visualmente, os seus olhos rastreiam naturalmente de volta aos cabeçalhos para compreender o que um valor particular representa. Os leitores de ecrã replicam este comportamento anunciando os cabeçalhos relevantes conforme os utilizadores navegam entre células — mas apenas quando os cabeçalhos estão adequadamente marcados no HTML.
Sem associações adequadas de cabeçalhos, um leitor de ecrã pode anunciar um valor de célula como “28:04” sem contexto. O utilizador não teria forma de saber o que esse número representa, a quem pertence ou em que categoria se enquadra. Esta é uma barreira crítica de acessibilidade para pessoas cegas ou surdocegas.
Esta regra relaciona-se com o Critério de Sucesso 1.3.1 das WCAG 2.1 (Informação e Relações), que exige que a informação e relações transmitidas através da apresentação visual sejam programaticamente determináveis. É também exigido pelas diretrizes da Secção 508, que determinam que os cabeçalhos de linha e coluna sejam identificados para tabelas de dados e que a marcação seja usada para associar células de dados com células de cabeçalho para tabelas com dois ou mais níveis lógicos de cabeçalhos.
A regra axe td-has-header verifica tabelas que têm pelo menos 3 células de largura e 3 células de altura. Se qualquer <td> não vazio numa tal tabela não tiver um cabeçalho associado, a regra falha.
Como corrigir
Existem duas técnicas principais para associar células de dados com cabeçalhos:
Usar <th> com scope
Esta é a abordagem mais simples e preferida para tabelas diretas. Substitua os elementos <td> das células de cabeçalho por elementos <th> e adicione um atributo scope:
-
Use
scope="col"para cabeçalhos de coluna. -
Use
scope="row"para cabeçalhos de linha.
Os leitores de ecrã usam o atributo scope para determinar que células de dados pertencem a que cabeçalho. Esta abordagem funciona bem para tabelas onde cada coluna e linha tem um único cabeçalho.
Usar id e headers
Para tabelas complexas — como aquelas com células fundidas, múltiplos níveis de cabeçalhos ou estruturas irregulares — use o método id e headers. Dê a cada <th> um id único, depois adicione um atributo headers a cada <td> listando os valores id de todos os cabeçalhos que se aplicam àquela célula, separados por espaços.
Este método é mais verboso mas permite definir explicitamente exatamente que cabeçalhos se relacionam com cada célula de dados, independentemente da complexidade da tabela. Sempre que possível, considere dividir uma tabela complexa em múltiplas tabelas mais simples, o que beneficia todos os utilizadores.
Exemplos
Falhando: tabela sem cabeçalhos
Esta tabela não tem elementos <th> de todo, por isso os leitores de ecrã não conseguem associar qualquer célula de dados com um cabeçalho.
<table>
<tr>
<td>Name</td>
<td>1 mile</td>
<td>5 km</td>
<td>10 km</td>
</tr>
<tr>
<td>Mary</td>
<td>8:32</td>
<td>28:04</td>
<td>1:01:16</td>
</tr>
<tr>
<td>Betsy</td>
<td>7:43</td>
<td>26:47</td>
<td>55:38</td>
</tr>
</table>
Passando: tabela simples com scope
Os cabeçalhos de coluna usam scope="col" e os cabeçalhos de linha usam scope="row", dando a cada <td> uma associação clara.
<table>
<caption>Greensprings Running Club Personal Bests</caption>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">1 mile</th>
<th scope="col">5 km</th>
<th scope="col">10 km</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Mary</th>
<td>8:32</td>
<td>28:04</td>
<td>1:01:16</td>
</tr>
<tr>
<th scope="row">Betsy</th>
<td>7:43</td>
<td>26:47</td>
<td>55:38</td>
</tr>
<tr>
<th scope="row">Matt</th>
<td>7:55</td>
<td>27:29</td>
<td>57:04</td>
</tr>
</tbody>
</table>
Quando um utilizador de leitor de ecrã navega para a célula que contém “26:47”, o leitor de ecrã anuncia algo como “Betsy, 5 km, 26:47” — fornecendo contexto completo.
Passando: tabela complexa com id e headers
Quando uma tabela tem múltiplos níveis de cabeçalhos ou células fundidas, o método id e headers dá-lhe controlo explícito sobre associações.
<table>
<caption>Race Results by Category</caption>
<thead>
<tr>
<td></td>
<th id="road" colspan="2">Road Races</th>
<th id="track" colspan="2">Track Events</th>
</tr>
<tr>
<td></td>
<th id="r5k">5 km</th>
<th id="r10k">10 km</th>
<th id="t800">800 m</th>
<th id="t1500">1500 m</th>
</tr>
</thead>
<tbody>
<tr>
<th id="mary">Mary</th>
<td headers="mary road r5k">28:04</td>
<td headers="mary road r10k">1:01:16</td>
<td headers="mary track t800">2:34</td>
<td headers="mary track t1500">5:51</td>
</tr>
<tr>
<th id="betsy">Betsy</th>
<td headers="betsy road r5k">26:47</td>
<td headers="betsy road r10k">55:38</td>
<td headers="betsy track t800">2:17</td>
<td headers="betsy track t1500">5:09</td>
</tr>
</tbody>
</table>
Neste exemplo, quando um leitor de ecrã chega a “26:47”, pode anunciar “Betsy, Road Races, 5 km, 26:47” porque o atributo headers lista explicitamente todos os três valores id de cabeçalho relevantes.
Pontos-chave a recordar
-
Use sempre
<th>para células de cabeçalho, não elementos<td>estilizados. -
Adicione um
<caption>para dar à sua tabela um nome descritivo. -
Use
scopepara tabelas simples eid+headerspara as complexas. -
Células
<td>vazias são excluídas desta regra — apenas células de dados não vazias precisam de associações de cabeçalho. - O estilo visual (bordas, fontes, fundos) deve ser tratado com CSS e não tem impacto na marcação de acessibilidade.
Learn more:
Ajude-nos a melhorar os nossos guias
Detecte problemas de acessibilidade automaticamente
O Rocket Validator examina milhares de páginas com Axe Core e o W3C Validator, encontrando problemas de acessibilidade em todo o seu site.