Critérios de Sucesso WCAG · Level A

WCAG 3.3.1: Identificação de Erros

A WCAG 3.3.1 exige que, quando um erro de entrada for detectado automaticamente, o item com erro seja identificado e o erro seja descrito ao usuário em texto. Isso garante que pessoas com deficiência possam reconhecer, compreender e corrigir erros ao preencher formulários.

O Que Esta Regra Significa

WCAG 3.3.1 Identificação de Erros é um critério de sucesso de Nível A sob o princípio Compreensível. Ele afirma: "Se um erro de entrada for detectado automaticamente, o item que está em erro é identificado e o erro é descrito ao usuário em texto." Em termos práticos, sempre que seu site ou aplicação validar automaticamente a entrada do usuário — seja no envio do formulário, na perda de foco do campo ou em tempo real — duas coisas devem acontecer se um erro for detectado: o campo ou controle específico que contém o erro deve ser claramente identificado, e a natureza do erro deve ser comunicada usando conteúdo em texto real (não apenas cor, ícone ou som).

O critério se aplica a qualquer situação em que dados sejam coletados de usuários e a validação ocorra automaticamente. Isso inclui elementos de formulário HTML como <input>, <select>, <textarea>, bem como widgets interativos personalizados construídos com ARIA. Abrange validação no lado do cliente disparada por JavaScript, validação nativa do navegador usando atributos como required, pattern, minlength e type, bem como resultados de validação no lado do servidor renderizados após o recarregamento da página ou injetados dinamicamente no DOM.

Um acerto exige que: (1) cada campo com erro esteja programaticamente associado a uma mensagem de erro — normalmente via aria-describedby ou aria-errormessage — para que tecnologias assistivas possam anunciá-la; (2) a mensagem de erro esteja em texto simples visível na interface (não oculta de usuários videntes); e (3) o texto descreva claramente o que deu errado, não apenas que algo deu errado. Por exemplo, "Endereço de e-mail é obrigatório" é uma descrição de erro válida, enquanto exibir apenas uma borda vermelha ou um ícone de exclamação sem alternativa em texto é uma falha.

Uma falha ocorre quando: erros são indicados apenas por mudanças de cor (borda vermelha sem texto), erros são anunciados apenas via role="alert" sem identificar qual campo foi afetado, o texto da mensagem de erro está vazio ou é genérico (por exemplo, "Entrada inválida"), ou mensagens de erro existem no DOM mas não estão programaticamente vinculadas ao campo correspondente, de modo que leitores de tela não conseguem associá-las.

WCAG 3.3.1 não se aplica quando não ocorre detecção automática — por exemplo, se um formulário é enviado e o servidor simplesmente recarrega a página sem qualquer indicação do que deu errado, isso é uma falha de usabilidade separada, mas está fora do escopo estrito deste critério. No entanto, se o seu sistema realiza detecção automática (o que praticamente todos os formulários modernos fazem), o critério está totalmente em escopo. Não há exceções definidas dentro do próprio critério para tipos específicos de entrada ou casos de uso.

Por Que Isso Importa

A identificação de erros afeta diretamente vários grupos de pessoas com deficiência de maneiras significativas. Para usuários cegos e com baixa visão que dependem de leitores de tela como NVDA, JAWS ou VoiceOver, uma borda vermelha ou um ícone de aviso não comunica nada. Se uma mensagem de erro não estiver presente como texto real e não estiver programaticamente associada ao campo com erro, o leitor de tela não a anunciará, e o usuário pode enviar um formulário repetidamente sem entender por que ele está falhando. De acordo com a Organização Mundial da Saúde, aproximadamente 2,2 bilhões de pessoas no mundo têm algum tipo de deficiência visual, e milhões dependem diariamente de tecnologia assistiva para interagir com conteúdo na web.

Para usuários com deficiências cognitivas — incluindo dislexia, transtorno de déficit de atenção e comprometimentos de memória — mensagens de erro vagas como "Algo deu errado" criam barreiras significativas. Esses usuários se beneficiam enormemente de texto de erro preciso e descritivo que lhes diga exatamente qual campo precisa de correção e qual deve ser o formato ou valor correto. Por exemplo, em vez de "Data inválida", uma mensagem como "A data de nascimento deve estar no formato DD/MM/AAAA" é muito mais acionável.

Usuários com deficiências motoras que navegam por teclado ou dispositivos de varredura despenderão esforço significativo para percorrer um formulário. Quando um erro é pouco claro ou não identificado, eles precisam atravessar novamente todo o formulário para encontrar o problema, aumentando muito o custo cognitivo e físico de concluir o formulário. Uma identificação clara de erros permite que esses usuários saltem diretamente para o campo problemático.

Considere este cenário do mundo real: uma cidadã ou um cidadão turco tentando se registrar em um portal de e-serviços do governo para solicitar um benefício por deficiência. O formulário exige um número de identificação nacional em um formato específico. A pessoa, que é cega, insere seu número de identificação. Ao enviar, o formulário é recarregado com campos destacados em vermelho, mas sem texto de erro associado. O leitor de tela anuncia apenas os rótulos dos campos novamente — a pessoa não tem ideia do que deu errado ou qual campo é o problema. Ela abandona o processo completamente, perdendo o acesso a um serviço público crítico. Esta é precisamente a situação que a WCAG 3.3.1 foi projetada para evitar.

Além da acessibilidade, a identificação clara de erros melhora as taxas de conversão e a usabilidade para todos os usuários. Estudos em pesquisa de UX mostram consistentemente que mensagens de erro inline descritivas reduzem o abandono de formulários. De uma perspectiva de SEO, sinais aprimorados de engajamento do usuário — incluindo maior tempo no site e envios de formulários bem-sucedidos — influenciam positivamente o ranqueamento de busca ao longo do tempo.

Regras Relacionadas do Axe-core

WCAG 3.3.1 exige testes manuais para verificação completa. Isso ocorre porque ferramentas automatizadas podem detectar a presença ou ausência de padrões estruturais (como aria-describedby ou aria-errormessage), mas não podem avaliar se o conteúdo em texto de uma mensagem de erro é significativo, preciso ou suficiente para ajudar o usuário a entender e corrigir o erro. Uma ferramenta automatizada vê que existe um elemento com role="alert"; ela não pode julgar se a mensagem "Erro na linha 4" descreve adequadamente uma falha de validação para um usuário de leitor de tela.

  • aria-required-attr: Esta regra do axe-core verifica se elementos com determinados papéis ARIA possuem todos os atributos ARIA obrigatórios. Embora não seja exclusivamente uma regra de identificação de erros, é relevante porque um campo de formulário em estado de erro que usa role="textbox" ou similar sem os atributos obrigatórios pode deixar de transmitir informações de estado para tecnologias assistivas, prejudicando a comunicação do erro.
  • aria-valid-attr-value: Esta regra sinaliza casos em que atributos ARIA referenciam IDs que não existem no DOM. Por exemplo, se um campo usa aria-describedby="email-error" mas não existe nenhum elemento com id="email-error", a associação é quebrada e a mensagem de erro não será lida por leitores de tela. Este é um padrão de falha comum para 3.3.1.
  • Requisito de avaliação manual: Testadores devem disparar manualmente erros de validação e então usar um leitor de tela para confirmar que: o campo com erro é identificado pelo nome ou rótulo, a descrição do erro é anunciada, a mensagem é significativa e acionável, e o erro não é comunicado apenas por meios não textuais. Varreduras automatizadas não podem simular sequências de interação do usuário nem avaliar a qualidade semântica do texto da mensagem, tornando o julgamento humano indispensável para este critério.

Como Testar

  1. Varredura automatizada com axe DevTools ou Lighthouse: Execute uma varredura com axe DevTools na página que contém o formulário antes e depois de disparar erros de validação. Procure especificamente por violações relacionadas a referências quebradas de aria-describedby ou aria-errormessage, ausência de regiões role="alert" ou aria-live usadas para injeção dinâmica de erros, e campos de formulário sem rótulos (o que também impede a associação adequada de erros). No Lighthouse, verifique a auditoria de Acessibilidade em busca de violações relacionadas a formulários. Observe que um relatório automatizado limpo não confirma conformidade com 3.3.1 — ele apenas descarta certas falhas estruturais.
  2. Teste manual de navegação por teclado: Usando apenas o teclado (Tab, Shift+Tab, Enter, Espaço), tente enviar o formulário com valores intencionalmente incorretos ou ausentes. Verifique se: o foco se move para ou próximo ao primeiro campo com erro, cada mensagem de erro está visível na área de visualização, e as mensagens de erro identificam o campo específico pelo nome e descrevem o problema em texto simples.
  3. Teste com leitor de tela usando NVDA + Firefox: Abra o formulário no Firefox com o NVDA ativo. Envie o formulário com erros. Ouça com atenção: o NVDA anuncia qual campo tem um erro? A descrição do erro é lida em voz alta? Use Tab para entrar no campo com erro — o NVDA lê a mensagem de erro associada como parte da descrição acessível do campo? Se estiver usando regiões aria-live, verifique se o anúncio não é atrasado ou suprimido.
  4. Teste com leitor de tela usando VoiceOver + Safari (macOS/iOS): Repita o mesmo processo usando o VoiceOver no Safari. Use VO+Seta para a direita para ler o formulário após o envio. Confirme se cada campo com erro inclui o texto de erro em seu nome ou descrição acessível. No iOS, teste usando navegação por toque e gestos de deslizar.
  5. Teste com leitor de tela usando JAWS + Chrome: Com o JAWS em execução no Chrome, envie o formulário com erros. Use o cursor virtual do JAWS para navegar até cada campo de formulário com erro. Confirme se o texto da mensagem de erro está incluído na leitura do campo pelo JAWS. Verifique também o comportamento do modo de formulários do JAWS, já que esse modo suprime alguns anúncios de regiões dinâmicas.
  6. Auditoria de cor e pistas não textuais: Inspecione visualmente cada estado de erro. Remova ou desative temporariamente o CSS (usando as ferramentas de desenvolvedor do navegador ou um bookmarklet) e confirme se a identificação de erros ainda está presente como texto no DOM. Isso verifica se a comunicação de erros não depende apenas de cor ou iconografia.
  7. Verificação de injeção dinâmica: Para aplicações de página única ou formulários com validação em tempo real, use as ferramentas de desenvolvedor do navegador para inspecionar o DOM após um erro ser disparado. Confirme se o elemento de mensagem de erro existe no DOM, contém texto não vazio e é referenciado pelo campo correspondente via aria-describedby ou aria-errormessage.

Como Corrigir

Cenário 1: Erro indicado apenas por cor — Incorreto

<!-- Fail: red border added via class, no error text associated -->
<label for='email'>Email Address</label>
<input type='email' id='email' name='email' class='input-error'>
<!-- CSS sets border: 2px solid red on .input-error -->
<!-- No error message text is rendered in the DOM -->

Cenário 1: Erro indicado apenas por cor — Correto

<!-- Pass: error text is present, visible, and linked to the input -->
<label for='email'>Email Address</label>
<input
  type='email'
  id='email'
  name='email'
  class='input-error'
  aria-describedby='email-error'
  aria-invalid='true'
>
<!-- aria-invalid signals the error state to assistive technologies -->
<!-- aria-describedby links the input to its error message by ID -->
<p id='email-error' role='alert'>
  Please enter a valid email address, for example: [email protected]
</p>

Cenário 2: Resumo genérico de erro sem identificação de campo — Incorreto

<!-- Fail: a summary alert exists but does not identify which fields failed -->
<div role='alert'>
  <p>There are errors in the form. Please correct them and try again.</p>
</div>
<label for='phone'>Phone Number</label>
<input type='tel' id='phone' name='phone' class='is-invalid'>
<!-- No per-field error message; user cannot determine which field failed -->

Cenário 2: Resumo genérico de erro sem identificação de campo — Correto

<!-- Pass: summary lists specific fields in error, and each field has inline error text -->
<div role='alert' aria-labelledby='error-heading'>
  <h2 id='error-heading'>2 errors found. Please fix the following:</h2>
  <ul>
    <li><a href='#phone'>Phone Number: must contain only digits and be 10 characters long</a></li>
    <li><a href='#dob'>Date of Birth: required field — please enter your date of birth</a></li>
  </ul>
</div>
<label for='phone'>Phone Number</label>
<input
  type='tel'
  id='phone'
  name='phone'
  aria-describedby='phone-error'
  aria-invalid='true'
>
<!-- Inline error linked via aria-describedby -->
<p id='phone-error'>Phone Number must contain only digits and be 10 characters long.</p>

Cenário 3: Referência aria-describedby quebrada — Incorreto

<!-- Fail: aria-describedby references an ID that does not exist in the DOM -->
<label for='username'>Username</label>
<input
  type='text'
  id='username'
  name='username'
  aria-describedby='username-msg'
  aria-invalid='true'
>
<!-- The element with id='username-msg' was never rendered or was removed -->
<!-- Screen readers find no target and announce nothing for the description -->

Cenário 3: Referência aria-describedby quebrada — Correto

<!-- Pass: the referenced element exists in the DOM with matching ID -->
<label for='username'>Username</label>
<input
  type='text'
  id='username'
  name='username'
  aria-describedby='username-msg'
  aria-invalid='true'
>
<!-- Element with matching id is present and contains descriptive text -->
<span id='username-msg'>
  Username must be between 4 and 20 characters and contain only letters and numbers.
</span>

Cenário 4: Erro de validação em tempo real injetado dinamicamente — Incorreto

<!-- Fail: error injected into DOM but not associated with input; no live region -->
<label for='password'>Password</label>
<input type='password' id='password' name='password'>
<!-- After blur, JavaScript appends this element, but no aria-describedby on input -->
<div class='error-text'>Password is too short.</div>

Cenário 4: Erro de validação em tempo real injetado dinamicamente — Correto

<!-- Pass: error container pre-exists in DOM (empty), input references it; aria-live announces changes -->
<label for='password'>Password</label>
<input
  type='password'
  id='password'
  name='password'
  aria-describedby='password-error'
  aria-invalid='false'
>
<!-- Empty span present at page load; JavaScript populates text and sets aria-invalid='true' on error -->
<span id='password-error' aria-live='polite'></span>
<!-- JavaScript on blur: -->
<!-- document.getElementById('password-error').textContent = 'Password must be at least 8 characters.'; -->
<!-- document.getElementById('password').setAttribute('aria-invalid', 'true'); -->

Erros Comuns

  • Usar apenas mudanças de classe CSS (por exemplo, adicionar border-color: red) para indicar erros sem qualquer texto correspondente no DOM. A cor sozinha não é perceptível para usuários cegos ou com daltonismo e falha tanto em 3.3.1 quanto em 1.4.1.
  • Escrever aria-describedby no campo de entrada, mas apontando para um ID que é renderizado condicionalmente ou removido do DOM na redefinição da validação. A referência quebrada significa que o leitor de tela não encontra conteúdo associado e o erro fica efetivamente invisível para usuários de tecnologia assistiva.
  • Usar texto de placeholder como única mensagem de erro. O texto de placeholder desaparece quando o usuário começa a digitar, muitas vezes tem baixo contraste e não é anunciado de forma confiável por todos os leitores de tela como parte da descrição do campo durante estados de erro.
  • Injetar mensagens de erro dinamicamente no DOM sem garantir que estejam associadas ao campo pai via aria-describedby. Uma mensagem de erro visualmente adjacente não é automaticamente associada a um campo de entrada — o vínculo programático deve ser explícito.
  • Exibir um resumo de erro em nível de página sem vincular cada item do resumo ao campo específico com erro. Usuários de leitores de tela ou navegação por teclado precisam ser capazes de ir diretamente da descrição do erro ao campo que requer correção.
  • Definir aria-invalid='true' em um campo, mas sem fornecer texto de mensagem de erro. O atributo aria-invalid sinaliza que um campo está em estado de erro, mas não descreve o erro — ele deve ser combinado com uma mensagem descritiva.
  • Fornecer mensagens de erro genéricas demais, como "Entrada inválida" ou "Erro no campo". Essas descrições não explicam o que está errado ou como corrigir, falhando o requisito descritivo de 3.3.1 e tornando a correção de erros desnecessariamente difícil para todos os usuários.
  • Remover regiões aria-live ou role='alert' de contêineres de erro ao redefinir um formulário, fazendo com que os contêineres desapareçam antes que leitores de tela terminem de anunciar seu conteúdo. Anúncios de erro podem ser interrompidos, deixando o usuário sem saber o resultado da validação.
  • Confiar nas janelas de validação nativas do navegador (os pop-ups de tooltip padrão) sem personalização. Interfaces de validação nativas do navegador são inconsistentes entre combinações de navegadores e tecnologias assistivas e muitas vezes não atendem aos requisitos da WCAG para identificação e descrição em cenários de formulários complexos.
  • Colocar mensagens de erro visualmente distantes de seus campos associados — como apenas em uma caixa de alerta no cabeçalho — sem também fornecer mensagens inline próximas a cada campo. Usuários com baixa visão que ampliam a tela podem não ver o alerta no cabeçalho enquanto estão focados na área de entrada, e usuários de teclado precisam percorrer uma distância significativa para ler o erro.

Relação com os Regulamentos de Acessibilidade da Turquia

A Circular Presidencial 2025/10 da Turquia, publicada no Diário Oficial nº 32933 em 21 de junho de 2025, estabelece requisitos obrigatórios de acessibilidade na web para uma ampla gama de entidades que operam na Turquia. A circular adota a WCAG 2.2 como seu padrão técnico, tornando todos os critérios de sucesso de Nível A — incluindo WCAG 3.3.1 Identificação de Erros — legalmente obrigatórios para as organizações abrangidas.

O cronograma de conformidade definido pela circular é de um ano para instituições públicas e dois anos para entidades do setor privado a partir da data de publicação. Isso significa que instituições públicas devem alcançar conformidade com WCAG 2.2 Nível A até junho de 2026, e entidades cobertas do setor privado até junho de 2027.

As entidades abrangidas pela circular incluem uma ampla seção transversal de serviços digitais turcos. Instituições públicas — incluindo todos os ministérios do governo central, municípios, universidades públicas e agências públicas — são obrigadas a garantir que seus serviços digitais sejam acessíveis. No setor privado, a circular abrange plataformas de e-commerce, bancos e instituições financeiras, hospitais e prestadores de serviços de saúde privados, empresas de telecomunicações com 200.000 ou mais assinantes, agências de viagem, empresas de transporte privado e escolas privadas autorizadas pelo Ministério da Educação Nacional (MoNE).

Para todas essas entidades, a WCAG 3.3.1 é diretamente relevante sempre que formulários online são usados — o que, na prática, significa quase todos os pontos de contato digitais. Formulários de checkout de e-commerce, fluxos de abertura de conta bancária, portais de registro de pacientes de hospitais, formulários de solicitação de benefícios governamentais, sistemas de reserva de companhias aéreas e de ônibus e páginas de matrícula escolar dependem de validação de formulários. Se qualquer um desses sistemas detectar automaticamente um erro de entrada e não identificar o campo ou descrever o erro em texto, eles estarão em violação direta dos requisitos da circular.

A não conformidade com a circular pode expor as entidades abrangidas a escrutínio regulatório, risco reputacional e possíveis penalidades à medida que o arcabouço de fiscalização da acessibilidade digital da Turquia amadurece. Além da conformidade legal, a adesão à 3.3.1 demonstra um compromisso com a prestação de serviços inclusivos — garantindo que todos os cidadãos, incluindo aproximadamente 8,5 milhões de pessoas com deficiência na Turquia (segundo dados do TÜİK), possam acessar serviços essenciais online sem barreiras. Organizações que operam sob o framework de SDK da Accsible devem priorizar tanto a conformidade estrutural automatizada quanto testes manuais rigorosos para garantir que seu tratamento de erros satisfaça plenamente este critério fundamental.