Tenho um site com modais que funcionam via React Portals e eles funcionam muito bem, alimentados por uma biblioteca popular. No entanto, em um lugar, devido a várias razões sensatas, temos um modal personalizado que não está dentro de um portal e não é alimentado pela biblioteca.
Para acessibilidade, tentei definir o próprio modal como role="modal" e aria-modal="true" para dar uma dica aos leitores de tela de que eles devem ignorar o plano de fundo. No entanto, o plano de fundo não é ignorado. Este site menciona que às vezes você precisa de aria-hidden no plano de fundo. Ao verificar como o React Portal e a biblioteca fazem isso, ele adiciona um atributo aria-hidden ao corpo. Então, pensei em tentar.
No entanto, quando eu crio um useEffect para fazer isso e chamo document.body.setAttribute('aria-hidden', 'true')
, ele simplesmente me ignora. Eu sei que o código funciona, eu posso definir outros atributos, mas não este. Alguém de vocês sabe por que isso está acontecendo?
Edição: Para esclarecer o motivo pelo qual estou tentando fazer isso, esta é a árvore HTML do react-modal
, a biblioteca que usamos e que mencionei acima, com 1,7 milhão de downloads semanais:
Eu adoraria entender por que eles estão fazendo isso, especialmente quando o modal é um filho do corpo que está sendo escondido. Como um dos comentários aponta, isso é contra as diretrizes do Aria, parece que não deveria funcionar, é estranho, mas realmente funciona.
Quando tento isso em um snippet:
...Recebo o seguinte erro no console do Chrome:
Dito isso, na verdade vejo posteriormente que o
aria-hidden="true"
atributo foi adicionado ao corpo, então algo curioso pode estar acontecendo ali, talvez relacionado ao fato de<body/>
estar em um<iframe/>
.De qualquer forma, o aviso está absolutamente correto — o modal que você está jogando na página está contido dentro
<body/>
do elemento document , então colocararia-hidden="true"
o<body/>
ocultará todo o seu conteúdo, incluindo seu modal. Então, essa não é, obviamente, uma abordagem recomendada.Você está certo em aproveitar a página Padrões do Guia de Práticas de Criação ARIA e ver como eles recomendam a criação de um modal; como aqueles que escreveram a especificação, eles provavelmente terão a melhor, mais idiomática e bem suportada abordagem. No entanto, observarei que a seção à qual você está se referindo, na qual eles afirmam "às vezes você precisa de aria-hidden em segundo plano", tem algumas ressalvas importantes:
aria-hidden
definido comotrue
."Por favor, nunca , realmente nunca coloque aria-hidden=true no corpo.
Existem duas grandes categorias típicas de casos de uso para aria-hidden:
Significado de aria-hidden
Tecnicamente, aria-hidden diz ao navegador para remover o elemento da árvore de acessibilidade, conforme dado pelo aviso do console. A árvore de acessibilidade é a estrutura dada aos leitores de tela e outras ferramentas de assistência para que eles possam renderizar conteúdo para o usuário. Praticamente, no final, SE algo estiver ausente da árvore de acessibilidade, significa que os usuários de leitores de tela e usuários que usam outras ferramentas de assistência não o "verão". Ele está simplesmente ausente.
Se você colocar aria-hidden=true no corpo, significa que você remove tudo da árvore de acessibilidade, ou dito de outra forma, você está tornando a página inteira definitivamente inacessível. Simplesmente não há razão válida para fazer isso em 2025. É inaceitável.
O ideal é que você tente fazer o melhor para tornar seu site acessível. Mas mesmo que você não saiba como, esteja inseguro, com medo de fazer errado ou não queira (o que infelizmente é muito frequente), você não deve colocar um fim definitivo assim. Talvez seu site não seja muito acessível, mas ele ainda pode ser usado parcialmente até certo ponto com um leitor de tela. Em todo caso, alguma coisa, mesmo muito pouco, é sempre melhor do que nada.
Com aria-hidden, não há retorno. Ele se foi definitivamente, para sempre.
Uso correto de aria-hidden
Ocultar pequenos elementos totalmente inúteis para leitores de tela e outras ferramentas de assistência
Em geral, aria-hidden não deve ser usado para partes significativas de uma página, como um diálogo inteiro ou um parágrafo inteiro de texto. Ele deve ser reservado para coisas muito pequenas, definitivamente totalmente inúteis para usuários de leitores de tela e outras ferramentas de assistência.
Por exemplo, um bom uso típico é ocultar ícones de texto de botões ou outros elementos interativos, quando o elemento tem outro rótulo textual.
Neste exemplo, o ícone é totalmente inútil para usuários de leitores de tela, que não precisam saber que um ícone está lá. Sem aria-hidden, o leitor de tela poderia dizer algo não relacionado, algo como "caractere impronunciável", linha vazia ou qualquer coisa sem sentido. É melhor escondê-lo. Esquecer aria-hidden neste caso também pode colocar usuários de controle de voz em apuros. Para ativar o botão, eles podem precisar ler o rótulo de texto do botão, "Push me", mais o nome exato do ícone (se ele tiver um nome real).
Ocultar partes temporariamente inertes ou inacessíveis da página
Outro bom uso típico de aria-hidden é ocultar temporariamente elementos inalcançáveis. As palavras-chave aqui são temporary unreachable .
No caso de um diálogo, significa, coloque aria-hidden em tudo fora do diálogo enquanto ele estiver ativo. Então, quando ele ficar inativo, não esqueça de remover aria-hidden.
No entanto, você deve ser um pouco esperto: tudo dentro de aria-hidden=true é removido da árvore de acessibilidade . Então, se você colocar aria-hidden em todo o corpo, seu diálogo será escondido e se tornará inacessível também!
O mais simples seria ter uma estrutura como esta:
Quando o diálogo abrir, você pode simplesmente colocar aria-hidden=true em
<main>
, e quando o diálogo fechar, removê-lo. Além disso, você deve garantir que o foco permaneça em elementos dentro do diálogo. Você tem que definir tabindex=-1 para todos os elementos focáveis fora do diálogo, ou configurar uma armadilha de foco. E, claro, não se esqueça de remover tudo isso quando o diálogo for fechado.