Escrevendo JavaScript com acessibilidade em mente
Olá galera, mais uma tradução saindo do forno. E mais um texto sobre JavaScript. Desta vez, um texto falando de acessibilidade. Sem dúvida, este é um assunto fundamental quando se trata de web. Se o seu produto dependa que mais e mais pessoas, do público em geral, acessem o conteúdo do seu site, então não deixa de ler este texto, e meditar acerca das boas práticas para sites e sistemas acessíveis.
Antes de começar a tradução do texto, não posso deixar de pedir que, caso curte ele, recomende-o. E também, conheça o projeto guia de acessibilidade, um site feito para que programadores possam ter acesso a boas práticas na hora de tornar um site acessível. Não deixe de conferir.
Confira o texto original, de Manuel Matuzovic, quase meu chará :)
Em meu primeiro post, Escrevendo HTML com acessibilidade em mente(ainda não traduzido), eu expliquei o porque e como iniciar no assunto acessibilidade na web. Eu também compartilhei dicas de como você pode melhorar seu markup para tornar seus sites mais acessíveis. Algumas delas são muito básicas, porém, valiosas. Tudo se resume a duas das mais importantes regras não escritas no desenvolvimento front-end: Aprenda o básico e tenha tempo suficiente para planejar e escrever HTML. Com ambas, você e seu usuário irão se beneficiar de uma limpa e semântica marcação.
Felizmente, HTML não é a única linguagem que nós temos nos websites, Mas quanto mais complexa a linguagem, mais fácil as coisas podem dar errado e JavaScript é um exemplo de como pode ficar complexo. Ainda que 0 conteúdo seja o principal de nosso código, é fácil esquecer como nossos usuário irão interagir além do mouse ou touch pad, por exemplo, teclado ou leitores de tela. Neste segundo artigo, de quatro, sobre acessibilidade na web, eu trago algumas digas do que considerar ao escrever JavaScript, e como tornar seus componentes mais acessíveis.
JavaScript não é o inimigo
Antes de ler as dicas, eu tenho que destacar um ponto importante: tornar seu site acessível não significa quando escolher usar JavaScript ou não. Acessibilidade é sobre tornar conteúdo disponível para o maior número de pessoas possível, o que também inclui usuários com browsers mais antigos, conexões de internet mais lentas, restrições de segurança e por ai vai. A experiência sob condições como estas, onde JavaScript pode não funcionar ou demorar muito tempo para carregar pode não ser o ideal, mas ainda é bom o suficiente se o site é acessível e utilizável.
Se JavaScript estará disponível, então podemos tornar o uso ainda mais acessível. Sara Soueidan escreveu sobre a experiencia dela com a criação de um tooltip widget em Building a fully-accessible help tooltip. Ela explica como simples soluções em que não há nenhum JS trazem uma experiencia ruim, porque JS é importante para a acessibilidade.
Marco Zehe escreveu bastante conteúdo sobre JS e acessibilidade em JavaScript is not an enemy of accessibility!. Eu sugiro ler este texto.
Mas vamos ao que interessa?
Mantenha o foco no que é principal
É muito importante que nossos sites sejam navegáveis via teclado. Um grande números de nossos usuários contam com o teclado para navegar na web. Entre eles há as pessoas com problemas motores, pessoas cegas e pessoas que não tem as mãos ou não podem usar o mouse e afins.
Navegar em um site via teclado significa pular de foco de um elemento para o outro, na ordem em que aparecem no DOM. Isto é possível usando a tecla tab ou shift + tab para direção reversa. Elementos focáveis são, entre outros, links, butões e elementos de formulário. Eles são selecionados usando a tecla enter e, às vezes, espaço. Por serem focáveis e selecionáveis de diferentes formas, eles trazem uma série de funcionalidades por padrão. Tendo em vista isso, se faz importante escrever um HTML semântico e em ordem lógica. Elementos como <p>, <h2>, ou <div> não podem ser focados por padrão. Nós geralmente usamos tags como estas para criar componentes customizados usando JS, o que pode significar um problema com usuários que usam teclado.
Tornando elementos não focáveis em focáveis
É possível fazer elementos não focáveis em focáveis adicionando o atributo tabindex com um valor inteiro. Se o valor definido for 0 (zero), o elemento se torna focalizável e acessível via teclado.
Se o valor for um número negativo, o elemento é focalizável, (por exemplo, com JS) mas não acessível via teclado. Você também pode usar um valor maior que zero, mas não mudará a ordem natural do tab e é considerado um anti-pattern.
<h2 tabindex="0">A focusable heading</h2>
Se você quer aprender mais sobre tabindex, assista ao episódio do A11ycasts, Controlling Focus with tabindex, de Rob Dodson.
Focando elementos com JS
Mesmo que os elementos sejam focáveis, às vezes eles não estão na ordem correta no DOM. Para ilustrar isso, eu criei uma modal simples em HTML, CSS e JS (Demo aqui).
Se você usar a tecla tab para pular o botão que pressiona ente, o modal aparecerá. O comportamento esperado deveria ser o próximo elemento, que está dentro do modal, ser focado. Mas não é o que acontece, pois os elementos são focados até chegar a modal, pois ela está no final da página, na ordem do DOM. Você pode ver isso em ação no vídeo do Youtube.
Para resolver isso, a modal precisa ser focada, então podemos usar o JS:
HTML
// Add tabindex="0"
<div class="modal" id="modal2" tabindex="0">
...
</div>
JS
// Use the focus() method to set focus
function showModal() {
...var modal = document.getElementById('modal2');
modal.focus();...
}
Você pode ver isso em ação no exemplo atualizado (Demo aqui) passando o tab pelo botão e depois pressionando enter a modal novamente aparece. Porem, dessa vez ela pode ser focada. Isso é bom, porem, ainda temos alguns problemas.
Se eu fechar a modal com a tecla esc, o foco é perdido. Idealmente, o foco deveria ser direcionado para o botão em que foi aberto a modal. Sendo assim, precisamos armazenar o ultimo elemento focado em um variável.
document.activeElement traz o elemento focado no momento.
// Variable for storing the last focused element
var lastFocusedElement;function showModal() {
...// Store the last focused element
lastFocusedElement = document.activeElement;var modal = document.getElementById(modalID);
modal.focus();...
}
Agora que você tem uma referência para o botão, você pode novamente focá-lo quando a modal for fechada.
function removeModal() {
...// Return the focus to the last focused element
lastFocusedElement.focus();...
}
Eu atualizei o código em outro Pen (Demo aqui). A acessibilidade está bem melhor agora, mas ainda há espaços para melhoras.
É aconselhável que se mantenha o foco dentro da modal enquanto ela esteja aberta. Agora mesmo é possível usar a tab fora do modal. Eu não entrarei em detalhes aqui, mas para complementar, eu fiz um quarto pen chamado keyboard trap — armadilha de teclado, em tradução livre — (Demo aqui). O foco permanecerá dentro da modal enquanto ela estiver ativa.
Se você comparar o primeiro com o último pen verá um número maior de código. Isto provavelmente não é o perfeito, mas a solução final é muito melhor para uso.
Há um outro exemplo de modal acessível em um ótimo artigo chamado Usando Tabindex do pessoal do Google. Se você quiser aprender mais sobre testes com teclados, visite o WebAIM website. Lá há uma lista das mais comuns interações, e padrões de teclas para tais interações, e informações adicionais sobre coisas a se considerar durante o teste. Para mais exemplos sobre gerência de foco, há os links a seguir (vídeos):
- Gerencia de Foco usando CSS, HTML e JS, pelo egghead.io;
- O que é foco? do A11ycasts.
Se você precisa de um botão, use o elemento <button>
Eu já falei sobre botões no meu primeiro artigo, mas parece que muitas pessoas tentam simular um botão com elementos genéricos. Então, estarei batendo nesta tecla neste tópico.
Eu fiz um pen (debug mode aqui) para mostrar alguns dos problemas quando se usa span ou div como botão ao invés do próprio elemento ou um input. Se você usar a tab na página, verá que o primeiro botão será focado, mas o segundo não. Isso ocorre porque o primeiro é um elemento button e o segundo é uma div. Você pode resolver este problema acrescentando o atributo tabindex = 0 para a div que ela se transformará num elemento focalizável. É por isso que o terceiro e quarto elementos são focáveis, mesmo que sejam divs.
// Button and focusable
<button class="btn">I'm a button</button>// Div and not focusable
<div class="btn">I'm a div</div>// Still just a div, but focusable
<div class="btn" tabindex="0">I'm a div</div>// Button role and focusable
<div class="btn" tabindex="0" role="button">I'm a div</div>
A div-button é focalizável, mas ainda se comporta como uma div, ainda que você adicione um role button. Para mostrar isso, eu adicionei um simples evento click para todos os elementos .btn (pen aqui). Se você clicar nos botões, um alert será mostrado, mas se tentar usar uma tecla (enter ou espaço), somente o primeiro botão disparará o evento. Você deveria acionar um evento de tecla aos div-buttons para imitar o efeito padrão do botão, mas isso é totalmente desnecessário, mas por que? Por que já existe um elemento com características de botão, então o use.
Assista ao episódio Apenas use o botão, do A11ycasts, por Rob Dodsen ou leia Links, Botões, Submits e Divs de Adrian Roselli, para mais detalhes e exemplos.
Leitores de tela devem ser informados quando o conteúdo muda dinamicamente
Na verdade, leitores de tela mostram o conteúdo quando um elemento é focado ou o usuário comando o leitor usando comandos de navegação. Se o conteúdo é carregado dinamicamente e inserido no DOM, somente usuários que enxergam verão as mudanças acontecendo. ARIA Live Regions fornece uma série de opções para trabalhar com este problema. Eu irei mostrar um exemplo.
Vamos dizer que você tem um pagina de configurações de usuário em que você tem a possibilidade de editar dados e salvá-los. Quando o botão de salvar é clicado mudanças são salvadas sem haver um refresh na página. Um informação de alert informa ao usuário se as mudanças foram bem sucedidas ou não. Isso pode acontecer imediatamente ou levar um tempo. Eu me recordo de um vídeo rápido para mostrar a você o que acabo de falar.
Você pode ver que a ação foi bem sucedida, mas você não ouve isso. Leitores de tela não noticiam a mudança, mas há uma simples solução para este problema. Adicionando uma role status ou alert para caixa da mensagem, e os leitores de tela poderão falar quando o conteúdo for atualizado.
<div class="message" role="status">Changes saved!</div>
Se o texto da mensagem for alterado, o leitor de tela lerá essa mudança. Você pode ser isto em ação neste vídeo e dar uma olhada neste pen.
Seja polido com seus usuários
A diferença entre status e alert é que com alert será interrompido o leitor de tela caso haja algo para ser mostrado. Já com status, ele irá esperar o leitor de tela terminar o que estiver fazendo e então anunciar alguma coisa.
Há outro atributo chamado aria-live, que traz três valores, off, polite e assertive. Off é o valor padrão, aria-live="polite"
é equivalente ao role=“status”e aria-live="assertive"
ao role="alert"
. Em alguns casos pré definidos bem conhecidos, é melhor usar o valor padrão fornecido pelo region role. Também se um navegador não suporta o atributo role
você deve querer usar ambos os atributos. Léonie Watson compartilha alguns resultados de testes em Screen reader support for ARIA live regions.
<div role="alert" aria-live="assertive></div>
As vezes, faz sentido anunciar mais do que a mudança no conteúdo
Por padrão, os leitores de tela apenas apresentam conteúdo que foi alterado, mesmo que haja outro conteúdo na mesma region live, mas ocasionalmente faz sentido anunciar todo o texto. É possível mudar o comportamento padrão com o atributo aria-atomic
. Se você definí-lo como true
, tecnologias assistivas apresentarão o conteúdo inteiro do elemento.
Há uma demo deste caso feito por Paul J. Adam que compara diferentes regions lives. Ele também testou neste demo com VoiceOver no IOS 8.1 e gravou para você poder ver em ação. Eu sugiro que assista a essa gravação, disponível aqui. Se você quer entender melhor os casos de uso para o aria-atomic
.
Algumas coisas a se considerar
- Live Regions não movem o foco, somente disparam um anúncio de mudança de texto.
- Use
alert
somente para mudanças críticas.status
é melhor na maioria dos casos, porque é mais ‘polido’. - Evite criar alertas que desaparecem automaticamente porque podem desaparecer muito rapidamente.
- Durante meus testes, eu tive problemas com o VoiceOver. Esconder o alert usando CSS ou criando-o dinamicamente não funcionam em todas as vezes. Certifique-se de testar suas live regions em todos os diferentes navegadores e em diferentes softwares.
Claro, há um exemplo num episódio do A11casts chamado Allerts! do Rob Dodson que tem mais detalhes e exemplos. Heydon Pickering tem outros exemplos de live regions em sua coleção de exemplos de ARIAS.
Você não precisa adivinhar quais padrões de uso seus widgets devem fornecer
Muitas vezes é difícil pensar em todos os recursos que um widget deve fornecer em termos de navegação e acessibilidade. Felizmente, há um recurso chamado WAI-ARIA Authoring Practices 1.1 que ajuda-nos com isso.
Práticas autorizadas pelo WAI-ARIA é um guia para entender como usar a WAI-ARIA para criar uma rica aplcação na internet. Ela descreve recomendações de padrões de uso do WAI-ARIA e fornece uma introdução ao conceitos por trás deles
Lá há guias para construir accordions, sliders, tabs e muito mais.
Componentes JavaScript Acessíveis
Há também alguns links com exemplo de componentes acessíveis via JavaScript:
- Exemplos praticos usando a ARIA
- Modaal — Modaal é um plugin modal acessível da WCAG 2.0 Level AA
- Frend — Uma coleção de componentes modernos e acessíveis para o front-end
- Os padrões de projeto da A11Y
Se você tem mais links, por favor, compartilhe nos comentários :)
Recapitulando
Use o poder do JavaScript de aprimorar os seus sites do pontos de vista da acessibilidade. Administre o foco, informe a si mesmo sobre padrões comuns de uso e considere leitores de tela quando for manusear o DOM. Acima de tudo, não esqueça para quem você está desenvolvendo seus sites e de que precisa ser uma experiência divertida para eles.
Indo além
Este artigo é o segundo de uma série de quatro. Os outros ainda estão em trabalho e em breve serão lançados:
- Escrevendo HTML com acessibilidade em mente (em breve tradução)
- Escrevendo JavaScript com acessibilidade em mente
- Escrevendo CSS com acessibilidade em mente (Ainda não lançou)
- Aprenda como desenhar e desenvolver com acessibilidade em mente.
Bom pessoal, mais um texto sobre JS e espero que tenha gostado. Se gostou, não deixa de recomendar e compartilhar este texto. Valeu pessoal!