Accessibilidade em JavaScript: como tornar o site acessível para todos
\n\nImagine que você entra em um site e o botão "Comprar" não pode ser clicado com o mouse — apenas com o teclado. Ou você não vê a tela, e o leitor de tela simplesmente pula metade do conteúdo. Desagradável, não é? Pois para milhões de pessoas, essa é a realidade diária.
\n\nAccessibilidade (ou a11y) não é apenas um termo da moda. É uma forma de tornar seu código honesto. Acessibilidade em JavaScript significa fazer seu site funcionar para todos: para pessoas com deficiência visual, com dificuldades motoras, para aqueles que usam apenas o teclado ou controle de voz. E sim, também é sobre SEO: os mecanismos de busca adoram código limpo e semanticamente correto.
\n\nNeste artigo, vamos explorar exemplos reais em JavaScript que você pode implementar hoje mesmo. Sem enrolação — apenas código e prática.
\n\nPor que a acessibilidade é sua responsabilidade?
\n\nSe você programa em JavaScript, você controla o comportamento da interface. É o JS que mais frequentemente quebra a acessibilidade: modais dinâmicos, rolagens infinitas, selects personalizados. Os leitores de tela (programas de leitura de tela) não leem sua mente — eles leem o que você diz a eles através do HTML e ARIA.
\n\nA boa notícia: a maioria dos problemas pode ser corrigida em uma noite. A ruim: se você não pensar em acessibilidade desde o início, terá que reescrever tudo por semanas.
\n\nAtributos ARIA: sua principal ferramenta
\n\nARIA (Accessible Rich Internet Applications) é um conjunto de atributos que ajudam as tecnologias assistivas a entender o que está acontecendo na página. JavaScript é ideal para atualizar dinamicamente esses atributos.
\n\nExemplo 1: Atualização dinâmica de aria-live
\n\nSuponha que você tenha um chat onde as mensagens são carregadas sem recarregar a página. O leitor de tela deve anunciar a nova mensagem. Sem aria-live, o usuário simplesmente não saberá da atualização.
// Criando um contêiner para notificações\nconst liveRegion = document.createElement('div');\nliveRegion.setAttribute('aria-live', 'polite');\nliveRegion.setAttribute('aria-atomic', 'true');\nliveRegion.classList.add('sr-only'); // ocultar visualmente\ndocument.body.appendChild(liveRegion);\n\n// Função para adicionar mensagem\nfunction addChatMessage(message) {\n liveRegion.textContent = ''; // limpar\n liveRegion.textContent = `Nova mensagem: ${message}`;\n}\n\n// Exemplo de chamada\naddChatMessage('Olá! Como vai?');\n\nImportante: aria-live="polite" diz ao leitor de tela: "Anuncie quando terminar de ler o conteúdo atual". aria-live="assertive" interrompe a leitura — use para erros críticos.
Exemplo 2: Accordion personalizado
\n\nOs elementos padrão <details> e <summary> já são acessíveis, mas se você criar um accordion personalizado em JS, precisa adicionar funções e estados ARIA.
// Para cada seção do accordion\nconst accordionButton = document.querySelector('.accordion-button');\nconst accordionPanel = document.querySelector('.accordion-panel');\n\naccordionButton.setAttribute('aria-expanded', 'false');\naccordionButton.setAttribute('aria-controls', 'panel-1');\naccordionPanel.setAttribute('id', 'panel-1');\naccordionPanel.setAttribute('aria-hidden', 'true');\n\naccordionButton.addEventListener('click', () => {\n const isOpen = accordionButton.getAttribute('aria-expanded') === 'true';\n accordionButton.setAttribute('aria-expanded', !isOpen);\n accordionPanel.setAttribute('aria-hidden', isOpen);\n});\n\nAgora o leitor de tela entende que o botão controla o painel e sabe se ele está aberto ou fechado.
\n\nGerenciamento de foco: não deixe o usuário se perder
\n\nUm dos erros mais comuns em acessibilidade JavaScript é a perda de foco. Quando uma janela modal abre, o foco deve ser movido para dentro dela. Quando fecha, deve retornar ao botão que a acionou.
\n\n