Sobre esta regra de acessibilidade
A especificação WAI-ARIA define uma hierarquia rigorosa para muitos roles. Alguns roles só são significativos quando aparecem como filhos de roles pai específicos. Por exemplo, um tab deve ser propriedade de um tablist, um listitem deve ser propriedade de um list ou group, e um menuitem deve ser propriedade de um menu ou menubar. Quando estas relações pai-filho estão em falta, o role torna-se semanticamente órfão — as tecnologias assistivas como leitores de ecrã não conseguem comunicar o contexto, posição ou propósito do elemento ao utilizador.
Porque isto é importante
Esta regra relaciona-se com o Critério de Sucesso 1.3.1 do WCAG 2.0/2.1/2.2: Informação e Relações (Nível A), que exige que informação, estrutura e relações transmitidas visualmente também estejam disponíveis programaticamente. Quando um role ARIA não tem o seu pai obrigatório, a relação estrutural perde-se na árvore de acessibilidade.
Os utilizadores mais afetados incluem:
- Utilizadores cegos e surdocegos que dependem de leitores de ecrã. Sem o role pai correto, os leitores de ecrã não conseguem anunciar contexto como “item 3 de 5 numa lista” ou “separador 2 de 4.”
- Utilizadores com deficiências motoras que dependem de tecnologia assistiva para navegação. Os roles pai em falta podem quebrar os padrões esperados de interação por teclado para widgets compostos como menus, tablists e árvores.
O impacto no utilizador é crítico — um role órfão pode tornar um widget inteiro inutilizável para utilizadores de tecnologia assistiva.
Roles pai obrigatórios comuns
Aqui estão alguns roles frequentemente usados e os seus pais obrigatórios:
| Role filho | Role(s) pai obrigatório(s) |
|---|---|
listitem |
list ou group |
tab |
tablist |
tabpanel |
(associado através do padrão tablist) |
menuitem, menuitemcheckbox, menuitemradio |
menu, menubar, ou group |
treeitem |
tree ou group |
row |
table, grid, rowgroup, ou treegrid |
cell, gridcell |
row |
columnheader, rowheader |
row |
option |
listbox ou group |
Como corrigir o problema
-
Envolva o elemento no seu role pai obrigatório. A correção mais simples é garantir que a estrutura DOM reflete a hierarquia obrigatória. Coloque o elemento dentro de um contentor que tem o role pai correto.
-
Use
aria-ownsquando a estrutura DOM não corresponde. Se o elemento filho não pode ser um descendente DOM do pai (ex: devido a restrições de layout), pode usararia-ownsno elemento pai para estabelecer a relação programaticamente. O atributoaria-ownsdiz às tecnologias assistivas que o elemento referenciado deve ser tratado como filho, independentemente da posição DOM. -
Consulte a especificação WAI-ARIA para o role específico que está a usar para confirmar quais roles pai são obrigatórios.
Exemplos
Incorreto: listitem sem um pai list
O role listitem requer um pai com role="list" ou role="group", mas aqui está diretamente dentro de um div simples:
<div>
<div role="listitem">Maçãs</div>
<div role="listitem">Bananas</div>
<div role="listitem">Cerejas</div>
</div>
Correto: listitem dentro de um pai list
<div role="list">
<div role="listitem">Maçãs</div>
<div role="listitem">Bananas</div>
<div role="listitem">Cerejas</div>
</div>
Incorreto: tab sem um pai tablist
<div>
<button role="tab" aria-selected="true">Separador 1</button>
<button role="tab" aria-selected="false">Separador 2</button>
</div>
Correto: tab dentro de um pai tablist
<div role="tablist">
<button role="tab" aria-selected="true">Separador 1</button>
<button role="tab" aria-selected="false">Separador 2</button>
</div>
Correto: usando aria-owns quando a estrutura DOM difere
Quando as restrições de layout impedem o aninhamento do filho dentro do pai no DOM, use aria-owns para estabelecer a relação:
<div role="tablist" aria-owns="tab1 tab2">
<!-- Os separadores estão noutro local do DOM devido a necessidades de layout -->
</div>
<div id="tab1" role="tab" aria-selected="true">Separador 1</div>
<div id="tab2" role="tab" aria-selected="false">Separador 2</div>
Incorreto: menuitem fora de um menu
<div>
<button role="menuitem">Cortar</button>
<button role="menuitem">Copiar</button>
<button role="menuitem">Colar</button>
</div>
Correto: menuitem dentro de um menu
<div role="menu">
<button role="menuitem">Cortar</button>
<button role="menuitem">Copiar</button>
<button role="menuitem">Colar</button>
</div>
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.