Critérios de Sucesso WCAG · Level AAA

WCAG 2.4.12: Foco Não Obstruído (Aprimorado)

As WCAG 2.4.12 exige que, quando um componente de interface do usuário recebe foco do teclado, nenhuma parte desse componente seja ocultada por conteúdo criado pelo autor — o elemento em foco deve estar totalmente visível. Esse critério aprimorado (AAA) elimina a permissão de visibilidade parcial de seu equivalente AA, garantindo que pessoas que usam o teclado vejam sempre exatamente onde está o foco.

O Que Esta Regra Significa

WCAG 2.4.12 — Foco Não Obstruído (Aprimorado) — é o equivalente em nível AAA ao WCAG 2.4.11 (Foco Não Obstruído, AA). Enquanto o critério AA permite que um componente em foco esteja parcialmente visível, o critério AAA exige que o componente em foco esteja totalmente visível — nenhuma parte dele pode ser ocultada por conteúdo criado pelo autor quando recebe foco via teclado.

Em termos práticos, isso significa que, quando uma pessoa usa Tab para chegar a um elemento interativo como um link, botão, campo de formulário ou widget personalizado, toda a área delimitadora desse elemento deve estar desobstruída por qualquer cabeçalho fixo, rodapé fixo, sobreposição modal, banner de cookies, widget de chat ou qualquer outro conteúdo que o autor tenha colocado na página. A regra tem como alvo especificamente o conteúdo criado pelo autor; o W3C faz uma exceção explícita para conteúdo que a própria pessoa usuária moveu para obscurecer o indicador de foco — por exemplo, um painel flutuante que a pessoa arrastou para frente do elemento em foco. Nesse caso, a responsabilidade não é do autor.

Para ser aprovado em 2.4.12, é necessário que, ao receber foco, todo o componente em foco esteja visível dentro da área de visualização (viewport) e não seja coberto por nenhum elemento com posição fixa, sticky ou absoluta que esteja sob controle do autor da página. Há falha quando qualquer parte do limite visível do elemento em foco fica escondida atrás dessas sobreposições — mesmo um único pixel do anel de foco ou do próprio componente sendo recortado conta como falha em nível AAA.

É importante entender o que 2.4.12 não cobre. Ele não exige um estilo específico de indicador de foco (isso é tratado por 2.4.11 e 2.4.7). Não exige que os indicadores de foco tenham uma taxa de contraste mínima (coberto por 2.4.13). Ele trata especificamente da relação espacial entre o elemento em foco e outros conteúdos na página — o problema de camadas que surge mais comumente a partir de posicionamento fixed e sticky em CSS.

Elementos HTML afetados incluem qualquer elemento focável ou tabulável: <a>, <button>, <input>, <select>, <textarea>, <details>, elementos com tabindex e widgets interativos personalizados construídos com papéis ARIA. O critério se aplica a todos os contextos de navegação, incluindo iframes, diálogos e transições de rotas em aplicações de página única (SPA).

Por Que Isso Importa

A navegação por teclado é um método de acesso primário para uma ampla gama de pessoas. Pessoas com deficiências motoras — incluindo aquelas que vivem com condições como ELA, esclerose múltipla, paralisia cerebral ou lesão por esforço repetitivo — dependem inteiramente do teclado ou de dispositivos de acesso por varredura em vez de um mouse. Pessoas cegas e com baixa visão que utilizam leitores de tela também navegam pelo teclado e, embora sua tecnologia assistiva anuncie a posição do foco de forma audível, pessoas videntes que usam o teclado dependem inteiramente do indicador visual de foco para se orientar na página.

Quando o elemento em foco é obscurecido, mesmo que parcialmente, essas pessoas enfrentam uma experiência frustrante e potencialmente desorientadora: a página parece não oferecer nenhum elemento em foco, ou a pessoa precisa adivinhar onde está no documento. Em nível AA (2.4.11), a visibilidade parcial é tolerada — pelo menos parte do componente está visível, fornecendo uma pista. O critério AAA elimina completamente esse compromisso, reconhecendo que até mesmo um indicador de foco parcialmente oculto pode passar despercebido por pessoas com sensibilidade de contraste reduzida, visão em túnel ou condições cognitivas que tornam a varredura da tela mais exigente.

Considere um cenário concreto: um site de e-commerce turco usa uma barra de navegação fixa de 80px de altura no topo da área de visualização e um banner de consentimento de cookies sticky de 60px de altura na parte inferior. Uma pessoa que pressiona Tab para navegar pelos cards de produto pode perceber que a borda superior ou inferior do card em foco — incluindo seu anel de foco — desliza para baixo de uma dessas superfícies fixas. Sob WCAG 2.4.11 (AA), se qualquer parte do card ainda estiver visível, o site é aprovado. Sob 2.4.12 (AAA), o card inteiro deve estar totalmente visível. Essa distinção é significativa: um rótulo de botão parcialmente oculto combinado com um anel de foco parcialmente oculto pode tornar genuinamente impossível para uma pessoa com baixa visão determinar qual elemento está ativo ou qual ação ele executará.

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 deficiências motoras afetam centenas de milhões a mais. Melhorias na acessibilidade por teclado beneficiam não apenas esses grupos, mas também pessoas usuárias avançadas que preferem navegação por teclado pela rapidez, pessoas em dispositivos sem dispositivo apontador e pessoas em situações em que o controle motor fino está temporariamente comprometido.

Além do acesso para pessoas com deficiência, o foco totalmente visível melhora a usabilidade geral e reduz custos de suporte. Quando todas as pessoas — incluindo aquelas sem deficiência — conseguem acompanhar claramente a posição do foco, as taxas de conclusão de formulários melhoram e as taxas de erro diminuem. Para sites voltados ao mercado turco, demonstrar conformidade AAA sinaliza um programa de acessibilidade maduro e gera confiança tanto entre pessoas usuárias quanto entre equipes institucionais de compras.

Regras Relacionadas do Axe-core

WCAG 2.4.12 é classificado como exigindo testes manuais e faz parte das adições do WCAG 2.2. Não há nenhuma regra totalmente automatizada no axe-core que consiga detectar essa violação de forma confiável, e entender o porquê é importante para equipes que constroem seus pipelines de teste.

  • Inspeção manual — focus-not-obscured-enhanced (sem regra automatizada): Varredores automáticos de acessibilidade como o axe-core operam sobre o DOM estático ou um instantâneo do estado renderizado. Detectar se um elemento em foco está obscurecido exige: (1) simular foco de teclado em cada elemento interativo em sequência, (2) calcular o retângulo delimitador do elemento após o scroll induzido pelo foco, (3) identificar todos os elementos com posição fixed e sticky e seus retângulos delimitadores e (4) testar sobreposição geométrica. Embora a automação parcial seja teoricamente possível, a natureza dinâmica do comportamento de scroll, do CSS scroll-padding, do scroll suave e do gerenciamento de foco via JavaScript torna isso altamente pouco confiável na prática. Um elemento em foco que está perfeitamente visível em um tamanho de viewport pode estar totalmente obscurecido em outro. O axe-core classifica esse critério como exigindo julgamento humano e marca achados como “needs review” em vez de violações automáticas. Pessoas testadoras devem percorrer manualmente com Tab todos os elementos interativos e confirmar visualmente a visibilidade total em cada largura de viewport relevante.
  • scrollable-region-focusable (regra do axe): Embora não mapeada diretamente para 2.4.12, essa regra do axe sinaliza elementos dentro de regiões roláveis que são focáveis, mas podem não rolar corretamente para a área visível. É um sinal relacionado que indica problemas de gerenciamento de scroll que podem fazer com que o foco seja obscurecido por cabeçalhos ou rodapés fixos — o modo de falha mais comum para 2.4.12.

Como ferramentas automatizadas não conseguem capturar de forma confiável violações de 2.4.12, as organizações precisam incorporar percursos manuais de teclado em seu processo de QA, idealmente em múltiplos tamanhos de viewport e com todas as camadas de UI persistentes (barras de navegação, widgets de chat, banners de cookies, avisos de GDPR) ativas.

Como Testar

  1. Varredura automatizada de base: Execute axe DevTools ou Lighthouse na página para identificar quaisquer problemas relacionados, como violações de scrollable-region-focusable ou problemas de overflow em CSS. Esses achados, embora não sejam violações diretas de 2.4.12, indicam áreas da página mais propensas a causar problemas de foco obscurecido. No axe DevTools, filtre pelos critérios do WCAG 2.2 e revise quaisquer itens “needs review” relacionados à visibilidade do foco.
  2. Identifique todo o conteúdo sobreposto persistente: Antes dos testes de teclado, catalogue visualmente cada elemento com position: fixed ou position: sticky na página — tipicamente barras de navegação, banners de cookies, widgets de chat, botões de ação flutuantes e barras de ferramentas no rodapé. Anote suas alturas e posições para saber quais zonas da área de visualização eles ocupam.
  3. Percurso de navegação por teclado: Começando do topo da página (ou após dispensar qualquer modal inicial), pressione Tab repetidamente para mover o foco por cada elemento interativo. Em cada parada de foco, verifique se o elemento em foco inteiro — incluindo seu indicador de foco visível (contorno ou anel) — está totalmente dentro da área de viewport desobstruída. Não aceite visibilidade parcial. Se qualquer parte do elemento ou de seu anel de foco desaparecer atrás de um elemento fixo, registre isso como uma falha de 2.4.12.
  4. Navegação reversa: Repita o percurso usando Shift+Tab para navegar para trás. Rodapés fixos costumam ser ignorados em testes apenas para frente, mas podem obscurecer elementos ao tabular em sentido reverso.
  5. Teste com leitor de tela usando NVDA + Firefox: Abra o NVDA, inicie o Firefox e navegue usando Tab. Quando o NVDA anunciar o foco em um elemento, confirme visualmente que o elemento está totalmente visível. O modo de foco do NVDA não rola automaticamente os elementos para fora de camadas fixas, portanto as violações podem diferir do comportamento nativo do navegador.
  6. Teste com leitor de tela usando VoiceOver + Safari (macOS/iOS): Ative o VoiceOver e use Tab (ou deslize no iOS) para navegar. O gerenciamento de scroll do Safari às vezes difere do do Chromium, potencialmente expondo estados de foco obscurecido que não aparecem no Chrome.
  7. Teste em viewports responsivos: Repita o percurso de teclado em pontos de quebra comuns — larguras de 320px, 768px, 1024px e 1440px. Elementos sticky frequentemente ficam mais altos ou mudam de posição em diferentes breakpoints, alterando quais zonas estão em risco.
  8. Teste após interações da pessoa usuária: Abra menus suspensos, expanda acordeões, dispare modais e navegue para novas rotas em aplicações de página única. Após cada mudança de estado, retome a navegação com Tab e volte a verificar a visibilidade total do foco, já que conteúdo dinâmico frequentemente introduz novas sobreposições fixas.

Como Corrigir

Cabeçalho Sticky Obstruindo Links em Foco — Incorreto

<!-- Fixed header with no scroll compensation -->
<header style='position:fixed; top:0; height:80px; background:#fff; width:100%;'>
  <nav>...</nav>
</header>

<main>
  <!-- When Tab reaches this link near the top of main, the header covers it -->
  <a href='/products'>View all products</a>
</main>

Cabeçalho Sticky Obstruindo Links em Foco — Correto

<!-- scroll-padding-top ensures focused elements scroll clear of the fixed header -->
<style>
  html {
    /* Match this value to the height of your fixed header */
    scroll-padding-top: 88px; /* 80px header + 8px breathing room */
  }
</style>

<header style='position:fixed; top:0; height:80px; background:#fff; width:100%;'>
  <nav>...</nav>
</header>

<main style='margin-top:80px;'>
  <!-- Focus now scrolls the element fully clear of the header -->
  <a href='/products'>View all products</a>
</main>

Banner de Cookies Cobrindo Elementos Interativos no Fundo da Viewport — Incorreto

<!-- Cookie banner fixed to the bottom, no scroll compensation -->
<div id='cookie-banner' style='position:fixed; bottom:0; height:72px; width:100%; background:#222;'>
  <button>Accept All</button>
  <button>Manage Preferences</button>
</div>

<footer>
  <!-- These links at the bottom of the page get covered by the cookie banner -->
  <a href='/privacy'>Privacy Policy</a>
  <a href='/terms'>Terms of Service</a>
</footer>

Banner de Cookies Cobrindo Elementos Interativos no Fundo da Viewport — Correto

<!-- Add scroll-padding-bottom and body padding to compensate for the banner height -->
<style>
  html {
    scroll-padding-bottom: 80px; /* 72px banner + 8px breathing room */
  }
  body {
    padding-bottom: 80px; /* Prevent content from being permanently under the banner */
  }
</style>

<div id='cookie-banner' style='position:fixed; bottom:0; height:72px; width:100%; background:#222;'>
  <button>Accept All</button>
  <button>Manage Preferences</button>
</div>

<footer>
  <!-- Links now scroll fully into the unobscured viewport area -->
  <a href='/privacy'>Privacy Policy</a>
  <a href='/terms'>Terms of Service</a>
</footer>

Gerenciamento de Foco em JavaScript Sem Considerar Camadas Fixas — Incorreto

<!-- SPA route change: focus moved to heading but scrollIntoView ignores header -->
<script>
function navigateTo(section) {
  const heading = document.querySelector('#' + section + ' h2');
  heading.setAttribute('tabindex', '-1');
  heading.focus();
  // scrollIntoView with no offset — heading scrolls behind fixed header
  heading.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
</script>

Gerenciamento de Foco em JavaScript Sem Considerar Camadas Fixas — Correto

<!-- Use scroll-margin-top on the target element, or manually offset scrollY -->
<style>
  .focus-target {
    /* scroll-margin-top offsets this element's scroll position from the top */
    scroll-margin-top: 96px;
  }
</style>

<script>
function navigateTo(section) {
  const heading = document.querySelector('#' + section + ' h2');
  heading.setAttribute('tabindex', '-1');
  // scroll-margin-top on the element handles the visual offset automatically
  heading.classList.add('focus-target');
  heading.focus();
  // scrollIntoView now respects scroll-margin-top, clearing the fixed header
  heading.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
</script>

Erros Comuns

  • Definir scroll-padding-top em body em vez de html: A propriedade CSS scroll-padding deve ser aplicada ao contêiner de scroll. Para scroll de página inteira, o contêiner de scroll é o elemento html, não body. Aplicá-la em body não tem efeito na maioria dos navegadores e é um dos erros de implementação mais comuns.
  • Fixar um valor em pixels para scroll-padding-top que não corresponde à altura real do cabeçalho em todos os breakpoints: Quando o cabeçalho se reduz para uma altura menor no mobile ou se expande para incluir uma barra de navegação secundária no desktop, o deslocamento estático fica incorreto. Use propriedades personalizadas de CSS atualizadas via JavaScript ou use calc() com unidades relativas para manter o valor em sincronia.
  • Esquecer de definir scroll-margin-top em alvos de âncoras na mesma página: Mesmo quando o scroll-padding-top global está correto para navegação com Tab, alvos de links âncora que recebem foco programático (por exemplo, links de pular para conteúdo, navegação por hash em SPAs) ainda podem ficar sob o cabeçalho, a menos que scroll-margin-top também seja definido nesses elementos específicos.
  • Dispensar o banner de cookies sem retestar: Muitas equipes testam a navegação por teclado apenas depois de aceitar o banner de cookies. Como o banner ocupa a parte inferior da viewport, elementos focáveis ancorados no fundo podem ser obscurecidos apenas enquanto o banner está ativo. Sempre teste com todas as camadas de UI persistentes em seu estado totalmente exibido.
  • Testar apenas em uma largura de viewport: Elementos sticky frequentemente mudam de altura, tornam-se visíveis ou desaparecem completamente em diferentes breakpoints. Uma falha em 375px pode não aparecer em 1440px, e vice-versa. Testar em apenas um tamanho deixa de cobrir uma proporção substancial de violações do mundo real.
  • Usar overflow: hidden em um contêiner pai para recortar indicadores de foco: Quando um componente de card ou contêiner tem overflow: hidden, o contorno de foco padrão do navegador em elementos filhos é recortado na borda do contêiner. Isso pode fazer o foco parecer totalmente visível na inspeção de elementos do DevTools, enquanto está visualmente cortado para a pessoa usuária.
  • Presumir que leitores de tela lidam com o scroll automaticamente, então testes visuais são desnecessários: Embora leitores de tela anunciem o elemento em foco de forma audível, pessoas videntes que usam teclado — incluindo aquelas que usam ferramentas de ampliação de tela — dependem inteiramente da posição visual. Um estado de foco visualmente obscurecido é uma falha real, independentemente do comportamento do leitor de tela.
  • Não testar diálogos modais e sobreposições tipo drawer: Quando um modal é aberto e o foco é movido para dentro dele, o backdrop ou a própria moldura do modal pode obscurecer o primeiro elemento em foco dentro do diálogo. Isso é especialmente comum em painéis tipo drawer que entram animados a partir da lateral ou da parte inferior.
  • Ignorar widgets de terceiros como bolhas de chat ao vivo e banners de anúncios intersticiais: Widgets de chat flutuantes (por exemplo, Intercom, Zendesk) e banners promocionais fixos injetados por gerenciadores de tags são conteúdo criado pelo autor e estão dentro do escopo deste critério. As equipes frequentemente os ignoram porque são gerenciados fora da base de código principal.
  • Confiar apenas em varreduras automáticas de acessibilidade e encerrar o ticket: Como 2.4.12 exige testes manuais, uma varredura limpa do axe-core não confirma conformidade. Encerrar tickets de acessibilidade com base apenas em resultados automatizados fará com que esse critério seja sistematicamente ignorado.

Relação com os Regulamentos de Acessibilidade da Turquia

O Decreto Presidencial 2025/10 da Turquia, publicado no Diário Oficial nº 32933 em 21 de junho de 2025, estabelece requisitos obrigatórios de acessibilidade web e móvel para uma ampla gama de entidades que operam na Turquia. O decreto adota o WCAG 2.1 Nível AA como padrão básico de conformidade, o que significa que o WCAG 2.4.12 — como critério AAA do WCAG 2.2 — não é diretamente exigido pela regulamentação atual. No entanto, sua relação com o quadro de acessibilidade da Turquia é significativa por várias razões.

As entidades abrangidas pelo Decreto Presidencial 2025/10 incluem instituições públicas e órgãos governamentais em todos os níveis, plataformas de e-commerce, bancos e prestadores de serviços financeiros, hospitais e organizações de saúde, 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 organizações, alcançar conformidade com WCAG 2.1 AA é uma obrigação legal, e espera-se que o decreto seja aplicado por meio de mecanismos de auditoria administrados pelos órgãos de supervisão relevantes.

Embora a conformidade AAA não seja exigida pelo decreto, organizações em setores regulados têm fortes motivos práticos para buscar conformidade com o WCAG 2.4.12. Primeiro, o cenário regulatório turco está evoluindo: o decreto representa uma intensificação significativa da aplicação de acessibilidade em comparação com orientações anteriores, e revisões futuras podem adotar o WCAG 2.2 ou elevar o nível de conformidade. Organizações que adotarem práticas AAA agora estarão melhor posicionadas para mudanças regulatórias. Segundo, processos de compras públicas e o acesso ao mercado da UE favorecem cada vez mais fornecedores que podem demonstrar programas de acessibilidade aprimorados, e documentação de conformidade AAA oferece um diferencial competitivo.

Terceiro, e mais diretamente relevante para o WCAG 2.4.12, o critério aborda um modo de falha que afeta de forma desproporcional pessoas usuárias de tecnologia assistiva na Turquia — uma população estimada em vários milhões de pessoas quando deficiências motoras, visuais e cognitivas são consideradas em conjunto. Bancos, hospitais e portais de governo eletrônico que dependem fortemente de chrome de navegação fixa e camadas de notificação persistentes são precisamente os sites em que falhas de foco obscurecido são mais comuns. Investir em conformidade total com o WCAG 2.4.12 demonstra um compromisso genuíno em atender todas as pessoas usuárias, alinha-se com o espírito do decreto presidencial mesmo onde a letra ainda não o exige e reduz o risco jurídico e reputacional à medida que a fiscalização turca amadurece.

Para organizações que utilizam o SDK de overlay da Accsible, a plataforma oferece ferramentas para auditar caminhos de foco de teclado e identificar conflitos de posicionamento sticky, apoiando tanto os requisitos obrigatórios de nível AA do Decreto Presidencial 2025/10 quanto aprimoramentos AAA voluntários como o WCAG 2.4.12.