Sobre esta regra de acessibilidade
Quando os utilizadores navegam numa página web usando um teclado ou leitor de ecrã, eles movem-se através do que se chama “ordem de foco” — a sequência de elementos interativos que recebem foco. Cada vez que um elemento recebe foco, um leitor de ecrã anuncia o seu papel (por exemplo, “botão”, “link”, “caixa de verificação”) juntamente com o seu nome e estado. Este papel é a forma como os utilizadores compreendem que tipo de controlo encontraram e que ações podem tomar.
Se um elemento focalizável não tem papel — por exemplo, um <div> tornado focalizável com tabindex="0" — o leitor de ecrã pode ler o conteúdo de texto do elemento mas não fornecerá contexto sobre o que é o elemento. O utilizador ouve texto mas não faz ideia se deve pressionar Enter, inserir dados ou alternar um estado. Da mesma forma, se um elemento tem um papel inadequado como presentation ou um papel abstrato como widget, as tecnologias assistivas não conseguem transmitir padrões de interação significativos.
Este problema afeta principalmente utilizadores cegos e surdocegos que dependem de leitores de ecrã, e utilizadores com deficiências motoras que navegam exclusivamente com um teclado. Sem informação adequada sobre o papel, estes utilizadores não conseguem interagir de forma eficiente ou precisa com os controlos da página.
Por que razão os papéis importam
Esta regra alinha-se com as melhores práticas de acessibilidade recomendadas pela Deque e RGAA. Embora não corresponda a um único critério de sucesso das WCAG, suporta vários princípios:
- WCAG 4.1.2 (Name, Role, Value): Todos os componentes da interface de utilizador devem expor o seu papel, nome e estado às tecnologias assistivas.
- WCAG 2.1.1 (Keyboard): Toda a funcionalidade deve ser operável através de um teclado. A informação significativa sobre o papel é essencial para que os utilizadores de teclado compreendam o que podem fazer com um elemento focado.
Quando um elemento na ordem de foco tem um papel válido e apropriado, os leitores de ecrã podem:
- Anunciar o tipo de controlo (por exemplo, “botão”, “caixa de texto”, “item de menu”).
- Informar os utilizadores das interações disponíveis (por exemplo, “pressione Enter para ativar”, “use as setas do teclado para navegar”).
- Comunicar mudanças de estado (por exemplo, “selecionado”, “expandido”).
Como corrigir o problema
Use primeiro elementos HTML nativos
A correção mais simples e confiável é usar o elemento HTML nativo correto. Elementos nativos como <button>, <a>, <input> e <select> vêm com papéis incorporados, comportamento de teclado e suporte de acessibilidade — não são necessários atributos extra.
Adicione papéis ARIA a widgets personalizados
Se deve usar um elemento não semântico (como <div> ou <span>) como um controlo interativo, precisa de:
-
Adicionar um atributo
roleapropriado (por exemplo,role="button",role="checkbox",role="tab"). - Garantir que todas as interações de teclado necessárias estão implementadas.
-
Gerir estados e propriedades ARIA (por exemplo,
aria-checked,aria-expanded).
Evite papéis abstratos
ARIA define papéis abstratos como command, input, landmark, range, section, sectionhead, select, structure e widget. Estes existem apenas como parte da taxonomia de papéis e nunca devem ser usados diretamente em elementos. Use sempre um papel concreto.
Remova tabindex de elementos não interativos quando possível
Se um elemento não precisa de ser interativo, considere remover completamente o seu atributo tabindex para que não apareça na ordem de foco.
Papéis apropriados para conteúdo interativo
Aqui estão algumas categorias comuns de papéis válidos para elementos focalizáveis:
-
Papéis de widget:
button,checkbox,combobox,link,listbox,menu,menuitem,menuitemcheckbox,menuitemradio,option,radio,scrollbar,slider,spinbutton,switch,tab,textbox,treeitem -
Papéis de widget composto:
grid,menubar,radiogroup,tablist,toolbar,tree,treegrid -
Papéis de marco:
banner,complementary,contentinfo,main,navigation,region,search -
Papéis de estrutura de documento:
dialog,alertdialog,application,document,log,status,timer,tooltip
Exemplos
Incorreto: elemento focalizável sem papel
Este <div> pode receber foco, mas um leitor de ecrã não anunciará o que é:
<div tabindex="0" onclick="submitForm()">
Submeter
</div>
Um utilizador de leitor de ecrã ouvirá “Submeter” mas não saberá que se destina a ser um botão.
Correto: usando um botão HTML nativo
<button type="button" onclick="submitForm()">
Submeter
</button>
O elemento <button> tem um papel button incorporado. O leitor de ecrã anuncia “Submeter, botão.”
Correto: adicionando um papel ARIA a um widget personalizado
Se não pode usar um <button> nativo, adicione o papel apropriado e suporte de teclado:
<div role="button" tabindex="0" onclick="submitForm()" onkeydown="handleKeydown(event)">
Submeter
</div>
Agora o leitor de ecrã anuncia “Submeter, botão.” Também deve implementar onkeydown para lidar com as pressões das teclas Enter e Space, uma vez que um <div> não suporta nativamente essas interações.
Incorreto: usando um papel abstrato
<div role="command" tabindex="0">
Guardar
</div>
O papel command é abstrato e não deve ser usado em elementos. As tecnologias assistivas não o reconhecerão como um papel válido.
Correto: substituindo o papel abstrato
<div role="button" tabindex="0" onkeydown="handleKeydown(event)">
Guardar
</div>
Incorreto: papel não interativo num elemento focalizável
<span role="paragraph" tabindex="0" onclick="openMenu()">
Opções
</span>
O papel paragraph não é interativo. O elemento não se comportará como esperado para utilizadores de tecnologias assistivas, e pode nem sequer receber foco em alguns leitores de ecrã.
Correto: usando um papel de widget apropriado
<span role="button" tabindex="0" onclick="openMenu()" onkeydown="handleKeydown(event)">
Opções
</span>
Incorreto: caixa de verificação personalizada focalizável sem papel
<div tabindex="0" class="custom-checkbox" onclick="toggleCheck(this)">
Aceitar termos
</div>
Correto: caixa de verificação personalizada com papel e estado adequados
<div role="checkbox" tabindex="0" aria-checked="false" onclick="toggleCheck(this)" onkeydown="handleKeydown(event)">
Aceitar termos
</div>
O role="checkbox" diz ao leitor de ecrã que isto é uma caixa de verificação, e aria-checked comunica o seu estado atual. Lembre-se de atualizar aria-checked no seu JavaScript quando o estado muda.
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.