ARIA: veneno ou antídoto?

Como mentir para leitores de tela cura a acessibilidade sem passar sal!

Aaron Leventhal
Aaron Leventhal

O que é ARIA?

ARIA permite que os autores da Web criem uma realidade alternativa, vista apenas por leitores de tela 🤥

Às vezes, é necessário falar sobre a verdade ou até mesmo "mentir" para os leitores de tela sobre o que está acontecendo no conteúdo da Web. Por exemplo, "o foco está bem aqui!" ou "este é realmente um controle deslizante!". É como adicionar notas adesivas mágicas em cima de ferramentas e widgets no seu painel. Essas notas adesivas másicas fazem todos acreditarem no que está escrito nelas.

Sempre que existe uma nota adesiva mágica, ela substitui nossa crença sobre cada ferramenta ou algo sobre a ferramenta. Exemplo: "esta coisa aqui é uma pistola de cola!". Mesmo que ainda seja uma caixa azul vazia no painel, a nota adesiva mágica nos fará ver que é uma pistola de cola. Também podemos adicionar “e está 30% cheio!”. O leitor de tela informará que há uma pistola de cola 30% cheia.

A Web equivalente a isso é pegar um elemento de caixa simples (um div) com uma imagem dentro dele e usar ARIA para indicar que é um controle deslizante com valor 30 de 100.

O que não é ARIA?

ARIA não afeta a aparência de uma página da Web nem o comportamento de um usuário de mouse ou teclado. Somente os usuários de tecnologias assistivas notarão qualquer diferença do ARIA. Os desenvolvedores da Web podem adicionar qualquer ARIA arbitrário sem afetar os usuários que não estejam executando uma tecnologia adaptativa.

Leia corretamente: ARIA não faz nada para mudar o foco do teclado ou a ordem da tabulação. Isso tudo é feito em HTML, às vezes ajustado com partes de JavaScript.

Como funciona ARIA?

Um leitor de tela ou outra tecnologia adaptativa pede para os navegadores acessarem informações sobre cada elemento. Quando ARIA está presente em um elemento, o navegador recebe as informações e muda o que diz ao leitor de tela sobre esse elemento.

Por que ARIA?

Por que nós iríamos mentir para nossos usuários?!

Digamos que a loja on-line local não vende todos os widgets de que precisamos. Mas somos MacGyver, caramba. Podemos inventar nossos próprios widgets usando outros. Além disso, as sete coisas mais usadas de MacGyver são facas do exército suíço, chicletes, cordas de sapatos, fósforos, clipes de papel, velas de aniversário e fita adesiva. Ele as usa para fazer bombas e outras coisas que não ficam só por aí. Isso é bem semelhante a um autor da Web que precisa fazer uma barra de menu. As barras de menu são tão úteis que você pensaria que fariam parte de HTML, mas não são. Que pena! Você não achou que os autores ficariam satisfeitos com links e botões, certo? Portanto, o autor vai combinar um usando suas ferramentas favoritas: divs, imagens, estilo, gerenciadores de cliques, gerenciadores de pressionamento de tecla, spit e ARIA.

Às vezes, em vez de usar ARIA ao máximo, nós apenas a usamos como um aprimoramento. Pode ser útil colocar um pouco de ARIA em algum HTML que já funciona. Por exemplo, podemos querer que um controle de formulário aponte para um alerta de mensagem de erro relacionado a alguma entrada inválida. Ou podemos indicar que uma caixa de texto é usada para pesquisa. Esses pequenos ajustes podem tornar sites comuns mais utilizáveis com um leitor de tela.

Suporte a pessoas que clicam com o mouse

Vamos fazer uma barra de menus juntos. Mostramos vários itens em elementos de caixa genéricos chamados divs. Sempre que o usuário clica em um div, ele executa o comando correspondente. Ótimo, ele funciona para mouses clicker!

Em seguida, fazemos ela ficar bonita. Usamos CSS, ou seja, estilos, alinhando as coisas bem e colocando contornos visuais ao redor deles. Fazemos com que ela se pareça o suficiente com outras barras de menu que os usuários sabem intuitivamente que é uma barra de menus e como usá-la. Nossa barra de menu usa até mesmo uma cor de fundo diferente em qualquer item sobre o qual o mouse está, oferecendo ao usuário um feedback visual útil.

Alguns itens do menu são principais. Eles geram submenus filhos. Sempre que o usuário passa o cursor sobre um deles, iniciamos uma animação que desliza para fora do submenu filho.

É claro que isso é praticamente inacessível, como é o caso comum de várias coisas na Web, principalmente porque os assistentes dos padrões HTML não adicionam tudo o que um autor da Web precisa. E mesmo que tivessem, os autores da Web sempre iriam inventar uma versão especial.

Como tornar o teclado da barra de menus acessível

Como primeiro passo em direção à acessibilidade, vamos adicionar a acessibilidade do teclado. Esta parte usa apenas HTML, e não ARIA. Lembre-se de que ARIA não afeta aspectos importantes, como aparência, mouse ou teclado, para usuários sem tecnologias adaptativas.

Assim como uma página da Web pode responder ao mouse, ela também pode responder ao teclado. Nosso JavaScript detecta todas as teclas pressionadas e decide se isso é útil. Caso contrário, ele o joga de volta à página como um peixe que é muito pequeno para comer. Nossas regras são semelhantes a estas:

  • Se o usuário pressionar uma tecla de seta, vamos analisar os blueprints da barra de menus interna e decidir qual será o novo item de menu ativo. Vamos limpar todos os destaques atuais e destacar o novo item de menu para que o usuário não veja visualmente onde ele está. A página da Web precisa chamar event.preventDefault() para impedir que o navegador realize a ação normal (rolar a página, nesse caso).
  • Se o usuário pressionar a tecla Enter, poderemos tratá-la como um clique e realizar a ação apropriada (ou até mesmo abrir outro menu).
  • Se o usuário pressionar uma tecla que deveria fazer outra coisa, não coma! Jogue o conteúdo de volta na página conforme planejado pela natureza. Por exemplo, a barra de menus não precisa da tecla Tab, então basta colocá-la de volta. É difícil de acertar, e os autores muitas vezes estragam tudo. Por exemplo, a barra de menus precisa de teclas de seta, mas não de Alt + seta ou Command + seta. Esses são atalhos para mover para a página anterior/próxima no histórico da Web da guia do seu navegador. Se o autor não tiver cuidado, eles serão consumidos pela barra de menu. Esse tipo de bug acontece muito, e ainda nem começamos com ARIA!

Acesso do leitor de tela à nossa barra de menus

Nossa barra de menus foi criada com fita adesiva e divs. Como resultado, um leitor de tela não tem ideia do que seja. A cor de fundo do item ativo é apenas uma cor. Os divs dos itens de menu são apenas objetos simples, sem significado específico. Consequentemente, um usuário da nossa barra de menus não recebe instruções sobre quais teclas pressionar ou em qual item elas estão.

Mas isso não é justo! A barra de menu funciona bem para usuários que enxergam.

ARIA ao resgate. ARIA nos permite fingir para o leitor de tela que o foco está em uma barra de menus. Se o autor fizer tudo certo, nossa barra de menus personalizada será exibida no leitor de tela como a barra de menus de um aplicativo para computador.

A primeira, ARIA, é usar o atributo aria-activedescendant e defini-lo como o ID do item de menu ativo no momento, tendo o cuidado de atualizá-lo sempre que ele mudar. Por exemplo, aria-activedescendant="settings-menuitem". Essa mentira faz com que o leitor de tela considere nosso item ativo ARIA como foco, que é lido em voz alta ou mostrado em uma linha braille.

Explicação de ancestor, ancestor e ancestor

O termo descendente se refere ao fato de um item estar contido em algum lugar dentro de outro. O termo oposto é ancestral, ou seja, um item pertence aos ancestrais. Para o próximo contêiner para cima/para baixo, eles podem usar os termos mais específicos pai/filho. Por exemplo, imagine um documento com um parágrafo que contenha um link. O pai do link é um parágrafo, mas também tem o documento como ancestral. Por outro lado, o documento pode ter muitos filhos de parágrafos, cada um com links. Os links são todos descendentes do documento avô.

Voltar para aria-activedescendant. Ao usá-lo para apontar da barra de menus em foco para um item de menu específico, o leitor de tela agora sabe para onde o usuário se moveu, mas nada mais sobre o objeto. O que é esse div? É aí que entra o atributo "role". Usamos role="menubar" no elemento que o contém para o elemento inteiro, depois usamos role="menu" em grupos de itens e role="menuitem" em ... tambor, nos itens individuais do menu.

E se o item de menu puder levar a um menu filho? O usuário precisa saber disso, certo? Para um usuário com visão, pode haver uma pequena imagem de um triângulo no final do menu, mas o leitor de tela não sabe como ler imagens automaticamente, pelo menos neste momento. Podemos adicionar aria-expanded="false" em cada item de menu expansível para indicar que 1) há algo que pode ser expandido e 2) ele não está expandido. Como um toque extra, o autor precisa colocar role="none" no triângulo de imagem para indicar que ele serve apenas para fins de prettificação. Isso evita que o leitor de tela diga algo sobre a imagem que seria redundante e possivelmente irritante.

Como lidar com bugs

Bugs de teclado (HTML!)

Embora o acesso ao teclado faça parte do HTML básico, os autores estragam isso o tempo todo, seja porque não usam muito a navegação pelo teclado ou porque há muitas nuances para acertar.

Exemplos de bugs:

  • Uma caixa de seleção usa a barra de espaço para alternar, mas o autor se esqueceu de chamar preventDefault(). Agora, a barra de espaço ativará a caixa de seleção e a página para baixo, que é o comportamento padrão do navegador.
  • Uma caixa de diálogo modal ARIA quer capturar a navegação por guias dentro dela, e o autor esquece de permitir especificamente Control + Tab para acessar o navegador. Agora, Control+Tab apenas navega na caixa de diálogo, sem mudar de guia no navegador como deveria. Aff.
  • Um autor cria uma lista de seleção e implementa para cima/para baixo, mas não implementa a navegação inicial/final/pageup/pagedown ou da primeira letra.

Os autores devem seguir padrões conhecidos. Confira a seção Recursos para mais informações.

Para problemas puramente de acesso ao teclado, é útil tentar também sem um leitor de tela ou com o modo de navegador virtual desativado. Os leitores de tela geralmente não são necessários para descobrir bugs do teclado, e o acesso ao teclado é, na verdade, implementado com HTML, não ARIA. Afinal, ARIA não afeta itens básicos, como o comportamento do teclado ou do mouse, apenas para o leitor de tela sobre o que está na página da Web, o que está em foco no momento etc.

Bugs de teclado são quase sempre um bug no conteúdo da Web, especificamente no HTML e JavaScript, não em ARIA.

Bugs ARIA: por que existem tantos?

Existem muitos lugares em que os autores podem cometer erros de ARIA, e cada um deles levará a uma quebra completa ou a diferenças sutis. As sutis provavelmente são piores, porque o autor não entenderá a maioria deles antes de publicar.

Afinal, a menos que o autor seja um usuário experiente de leitor de tela, algo vai dar errado no ARIA. No exemplo da barra de menus, o autor poderia pensar que o papel "option" seria usado quando "menuitem" estava correto. Eles podem se esquecer de usar aria-expanded, esquecer de definir e limpar aria-activedescendant nos momentos certos ou esquecer de ter uma barra de menus com os outros menus. E as contagens de itens do cardápio? Normalmente, os itens de menu são apresentados pelos leitores de tela com algo como "item 3 de 5" para que o usuário saiba onde está. Geralmente, isso é contado automaticamente pelo navegador, mas, em alguns casos, e em alguns navegadores (em algumas combinações de leitor de tela, os números incorretos podem ser computados), e o autor precisa substituir esses números por aria-posinset e aria-setsize.

E isso são só as barras de menu. Pense em quantos tipos de widgets existem. Olhe para a especificação ARIA ou as práticas de criação, se desejar. Para cada padrão, há uma dúzia de maneiras de mau uso de ARIA. ARIA depende dos autores para saber o que eles estão fazendo. O que poderia dar errado, considerando que a maioria dos autores não são usuários de leitores de tela?

Em outras palavras, é 100% necessário que usuários reais de leitores de tela testem widgets ARIA antes de serem considerados entregáveis. Há muitas nuances. O ideal é que tudo seja testado com várias combinações diferentes de leitor de tela e navegador, devido às várias peculiaridades de implementação, além de algumas implementações incompletas.

Resumo

Em resumo, a mágica ARIA pode ser usada para substituir ou adicionar tudo o que o HTML diz. Ele pode ser usado para fazer pequenas mudanças na apresentação de acessibilidade ou para criar uma experiência inteira. É por isso que ARIA é incrivelmente eficiente e, ao mesmo tempo, perigoso para os nossos simpáticos autores da web locais, que geralmente não usam leitores de tela.

ARIA é apenas uma camada de marcação de substituição de verdade direta. Quando um leitor de tela pergunta o que está acontecendo, se ARIA existe, ele recebe a versão ARIA da verdade, em vez da verdade real subjacente.

Adendo 1: recursos adicionais

Referência híbrida com informações de teclado e exemplos de código

  • Práticas de criação ARIA do W3C: documenta as características importantes de navegação pelo teclado de cada exemplo e fornece código JS/CSS/ARIA funcional. Os exemplos são focados no que funciona hoje e não abrangem dispositivos móveis.

Adendo 2: para que o ARIA é mais usado?

Como ARIA pode substituir ou complementar verdades pequenas ou grandes, geralmente útil para dizer coisas que são importantes para o leitor de tela.

Aqui estão alguns usos comuns de ARIA.

  • Widgets especiais que não existem em HTML, como barra de menus, preenchimento automático, árvore ou planilha
  • São widgets que existem em HTML, mas o autor inventou os próprios, possivelmente porque precisavam ajustar o comportamento ou a aparência do widget normal. Por exemplo, um elemento HTML <input type="range"> é basicamente um controle deslizante, mas os autores querem deixá-lo diferente. Para a maioria das coisas, o CSS pode ser usado, mas para input type="range", o CSS é estranho. Um autor pode fazer o próprio controle deslizante e usar role="slider" nele com aria-valuenow para dizer qual é o valor atual.
  • As regiões ativas informam aos leitores de tela "nessa área da página, qualquer mudança que possa ser informada ao usuário".
  • Pontos de referência (o HTML tem equivalentes agora). Eles são parecidos com títulos, porque ajudam os usuários de leitores de tela a encontrar o que querem com mais rapidez. No entanto, eles são diferentes porque contêm toda a área relacionada. Por exemplo, "este contêiner é a área principal da página" e "este contêiner aqui é um painel de navegação".

Adendo 3: o que é uma API de acessibilidade?

Uma API de acessibilidade é como um leitor de tela ou outra TA sabe o que está na página e o que está acontecendo no momento. Os exemplos incluem MSAA, IA2 e UIA. E isso é apenas o Windows! Uma API de acessibilidade tem duas partes:

  • Uma "árvore" de objetos que representa uma hierarquia de contêiner. Elas são como bonecas russas, mas cada uma delas pode conter outras. Por exemplo, um documento pode conter vários parágrafos e um parágrafo pode ter texto, imagens, links, negrito etc. Cada item na árvore de objetos pode ter propriedades como um papel (o que eu sou?), um nome/rótulo, um valor inserido pelo usuário, uma descrição, bem como estados booleanos como focalizável, focado, obrigatório, marcado. ARIA pode substituir qualquer uma dessas propriedades. O leitor de tela usa a árvore para ajudar o usuário a navegar no modo de buffer virtual, por exemplo, "vá para o próximo cabeçalho".
  • Uma série de eventos que ocorrem descrevendo mudanças na árvore, como "o foco agora acabou aqui!". O leitor de tela usa os eventos para informar ao usuário o que acabou de acontecer. Quando a marcação HTML ou ARIA importante muda, um evento é disparado para informar ao leitor de tela que algo mudou.

Normalmente, os autores usam apenas HTML, que mapeia bem para essas APIs de acessibilidade. Quando o HTML não é suficiente, ARIA é usada, e o navegador substitui a semântica HTML antes de enviar a árvore de objetos ou os eventos para o leitor de tela.