Programação Por Equipe DevBras

Capa do artigo: Botão só com ícone: como dar o nome que o leitor de tela anuncia

Botão só com ícone: como dar o nome que o leitor de tela anuncia

Deixe a barra de ícones limpa sem criar botões mudos: o desenho vira decoração, o botão recebe um nome que descreve a ação, e estado e contraste não dependem só da cor.

O painel de pedidos ganhou uma barra elegante: lápis, duas folhas, impressora e lixeira. Quem enxerga entende em meio segundo. Quem usa leitor de tela ouve "botão, botão, botão, botão" e precisa apertar cada um para descobrir qual apaga o pedido. A biblioteca de ícones entregou o desenho; o nome do botão ela não coloca por você.

A resposta curta: o ícone fica escondido da tecnologia assistiva com aria-hidden="true", e o botão recebe um nome acessível que descreve a ação, não o desenho. Esse nome vem de texto visível, de um texto escondido só visualmente ou de aria-label. Depois, confira no inspetor de acessibilidade do navegador se cada botão tem nome.

Por que o botão fica mudo

Bibliotecas como Bootstrap Icons e Font Awesome desenham o ícone de dois jeitos: com SVG ou com fonte de ícones, em que um elemento vazio recebe uma classe e o CSS injeta um caractere especial. Nos dois casos, não existe texto real dentro do botão. O navegador calcula o "nome acessível" de um botão a partir do conteúdo de texto e de alguns atributos; se não há nada, o nome sai vazio.

Com fonte de ícones, a situação pode ser pior que o silêncio. Alguns leitores tentam ler o caractere injetado, que fica numa área de código reservada da fonte, e anunciam um símbolo sem sentido. Por isso o ícone precisa ser escondido explicitamente, e o nome precisa vir de outro lugar.

Este guia foca em fonte de ícones e no padrão de botões de barra de ferramentas. Se você usa SVG inline, os detalhes de title e role no próprio SVG estão em ícone SVG de biblioteca precisa de nome. Para escolher quais ícones usar, veja como escolher ícones sem poluir a interface.

Três jeitos certos de nomear o botão

O exemplo é a barra de um pedido no painel da loja. O código usa as classes do Bootstrap 5 e do Bootstrap Icons.

<!-- Errado: o leitor anuncia só "botão" -->
<button type="button"><i class="bi bi-trash"></i></button>

<!-- 1. Texto visível: o ícone é só decoração -->
<button type="button" class="btn btn-outline-danger">
  <i class="bi bi-trash" aria-hidden="true"></i> Excluir
</button>

<!-- 2. Texto escondido só visualmente -->
<button type="button" class="btn btn-outline-danger">
  <i class="bi bi-trash" aria-hidden="true"></i>
  <span class="visually-hidden">Excluir pedido 1042</span>
</button>

<!-- 3. aria-label no próprio botão -->
<button type="button" class="btn btn-outline-danger" aria-label="Excluir pedido 1042">
  <i class="bi bi-trash" aria-hidden="true"></i>
</button>

Quando cabe, o primeiro é o melhor: todo mundo lê o mesmo texto, inclusive quem enxerga mas não reconhece o ícone. O segundo é útil porque o texto escondido é traduzido pelas ferramentas de tradução automática da página com mais frequência que um atributo. O terceiro é o mais curto e funciona bem em componentes.

A classe visually-hidden é a do Bootstrap 5; na versão 4, o equivalente se chamava sr-only. Se você não usa Bootstrap, a técnica é a mesma: o texto continua no DOM, mas é recortado para ocupar um pixel invisível. Não use display: none para isso, porque ele esconde o texto também do leitor de tela.

Passo a passo para revisar uma barra existente

  1. Liste todos os botões e links que mostram só ícone. Inclua os de fechar modal, abrir menu e os de paginação.
  2. Escreva, para cada um, o verbo da ação: "Editar", "Duplicar", "Imprimir", "Excluir". Se a mesma barra se repete em cada linha da tabela, inclua o objeto: "Excluir pedido 1042".
  3. Adicione aria-hidden="true" em todo elemento de ícone.
  4. Escolha um dos três padrões de nome e aplique em todos os botões da barra, para manter a consistência.
  5. Abra as ferramentas do navegador, selecione o botão e veja o painel de acessibilidade. No Chrome e no Edge, a aba Accessibility mostra o nome calculado; o Firefox tem um inspetor de acessibilidade próprio.
  6. Teste com um leitor real ao menos uma vez: NVDA no Windows, VoiceOver no macOS e no iPhone, TalkBack no Android.

Descreva a ação, não o desenho

"Lixeira" diz o que você vê; "Excluir pedido" diz o que acontece. A pessoa não quer saber que há uma impressora desenhada, quer saber se o botão imprime a etiqueta ou a nota. Nomes como "ícone de lápis" ou "imagem de lixeira" são o erro mais comum depois do nome vazio.

Um caso que pega muita gente: o botão tem texto visível curto, como "Enviar", e alguém coloca aria-label="Submeter formulário de cadastro". Quem usa controle por voz fala "clicar em Enviar" e nada acontece, porque o nome acessível não contém a palavra que está na tela. A regra prática: quando existe texto visível, o nome acessível começa com esse texto, ou simplesmente é ele.

Estado, tamanho e contraste também contam

A estrela de favorito que fica amarela quando ativa comunica estado só pela cor. Para quem não distingue a cor, ou não vê a tela, nada mudou. Em botões de alternância, use aria-pressed e troque também a forma do ícone, de contorno para preenchido:

<button type="button" aria-pressed="false" aria-label="Favoritar pedido 1042" id="fav-1042">
  <i class="bi bi-star" aria-hidden="true"></i>
</button>

<script>
  const botao = document.getElementById('fav-1042');
  botao.addEventListener('click', function () {
    const ativo = botao.getAttribute('aria-pressed') === 'true';
    botao.setAttribute('aria-pressed', String(!ativo));
    const icone = botao.querySelector('i');
    icone.classList.toggle('bi-star', ativo);
    icone.classList.toggle('bi-star-fill', !ativo);
  });
</script>

Repare que o nome não muda: o leitor anuncia "Favoritar pedido 1042, botão de alternância, pressionado". Trocar o rótulo para "Desfavoritar" e ao mesmo tempo usar aria-pressed cria uma frase contraditória.

Ícone é componente gráfico, então segue regras próprias. As diretrizes WCAG pedem contraste de pelo menos 3:1 para elementos gráficos necessários para entender a interface, e a versão 2.2 trouxe um critério de tamanho mínimo de alvo de toque. Um ícone cinza-claro de 14 pixels sobre fundo branco costuma falhar nos dois. Aumente a área clicável com espaçamento interno, mesmo que o desenho continue pequeno.

O atributo title não resolve sozinho

Muita gente coloca title="Excluir" e considera resolvido, porque aparece uma dica ao passar o mouse. O problema: a dica não aparece no toque nem no foco por teclado na maioria dos navegadores, e o suporte em leitores de tela varia. Use title, se quiser, como complemento visual, nunca como único nome. Para dicas visíveis acessíveis, um componente de tooltip que também abre no foco é o caminho.

Erros comuns

  • Botão só com o elemento do ícone: o leitor anuncia "botão" sem nome e a pessoa precisa adivinhar, às vezes apagando o que não queria.
  • Esquecer aria-hidden no ícone de fonte: alguns leitores anunciam o caractere interno da fonte, um ruído que se repete em cada linha da tabela.
  • Nome que descreve o desenho: "lápis" e "lixeira" obrigam a pessoa a traduzir metáfora em ação, e algumas metáforas não são universais.
  • Esconder o texto com display: none: o texto some também para a tecnologia assistiva e o botão volta a ser mudo.
  • Estado indicado só pela cor: quem não distingue a cor não sabe se o filtro ou o favorito está ativo.
  • aria-label diferente do texto visível: quem usa comando de voz fala o que vê na tela e o botão não responde.

Checklist

  • Todo botão e link só com ícone tem nome no painel de acessibilidade do navegador.
  • Todo elemento de ícone tem aria-hidden="true".
  • Os nomes são verbos de ação e, em listas repetidas, citam o item.
  • Botões com texto visível têm nome acessível que contém esse texto.
  • Botões de alternância usam aria-pressed e mudam a forma do ícone, não só a cor.
  • O ícone tem contraste suficiente com o fundo e a área de toque não é minúscula.
  • Nenhum botão depende só de title para ter nome.

Abra a tela mais usada do seu sistema, selecione cada botão de ícone no inspetor e leia o nome calculado. Quantos aparecem vazios, e qual deles a pessoa clicaria por engano se tivesse de adivinhar?

Avalie este artigo

Referência: https://icons.getbootstrap.com/