Seção 2

Comportamento

Scripts acessíveis, gerenciamento de foco, ausência de armadilhas de teclado, controle sobre conteúdo dinâmico e visibilidade do foco.

2.1

Tornar todo o conteúdo e as funcionalidades disponíveis por meio do teclado

WCAG A

Reforça a Rec. 1.8. Toda interação deve ser possível via teclado — incluindo menus suspensos, modais, carrosséis, abas e widgets customizados.

WCAG 2.1.1
Incorreto
<!-- ❌ Widget não acessível por teclado -->
<div class="abas">
  <div class="aba" onclick="mudarAba(0)">Dados</div>
  <div class="aba" onclick="mudarAba(1)">Documentos</div>
</div>
<div class="painel" id="painel-0">...</div>
Correto
<!-- ✓ Tabs com suporte ARIA e teclado -->
<div role="tablist" aria-label="Seções do portal">
  <button role="tab"
    aria-selected="true"
    aria-controls="painel-dados"
    id="tab-dados">
    Dados
  </button>
  <button role="tab"
    aria-selected="false"
    aria-controls="painel-documentos"
    id="tab-docs">
    Documentos
  </button>
</div>
<div role="tabpanel" id="painel-dados"
  aria-labelledby="tab-dados">
  ...
</div>
Dica

Consulte os padrões ARIA Authoring Practices (APG) do W3C para implementações de referência de tabs, acordeões, diálogos, menus e outros widgets acessíveis. Teste com Tab, Shift+Tab, setas e Enter.

2.2

Garantir que os objetos programáveis sejam acessíveis

WCAG A

Mapas, gráficos, visualizações interativas e outros conteúdos baseados em Canvas ou SVG devem ter alternativas textuais e ser operáveis por tecnologias assistivas.

WCAG 1.1.1WCAG 4.1.2
Incorreto
<!-- ❌ Canvas sem alternativa -->
<canvas id="grafico-receitas"
  width="800" height="400">
</canvas>
Correto
<!-- ✓ Canvas com alternativa semântica -->
<figure>
  <canvas id="grafico-receitas"
    role="img"
    aria-label="Gráfico de receitas 2024"
    aria-describedby="desc-grafico">
  </canvas>
  <figcaption id="desc-grafico">
    Receita total em 2024: R$ 28,4 bilhões.
    Crescimento de 12,3% em relação a 2023 (R$ 25,3 bi).
    <a href="receitas-2024.csv">
      Baixar dados em CSV
    </a>
  </figcaption>
</figure>
Dica

Para gráficos, forneça sempre os dados em formato tabular ou textual. Para mapas interativos, ofereça alternativa com lista de localizações. SVG acessível usa roles, títulos e descrições inline.

2.3

Não causar mudança de foco automática não solicitada

WCAG A

O foco de teclado não deve ser movido automaticamente para outro elemento sem ação do usuário. Isso desorenta leitores de tela e usuários que navegam por teclado.

WCAG 3.2.1WCAG 3.2.2
Incorreto
<!-- ❌ Foco movido automaticamente -->
<input type="text" id="digito-1" maxlength="1"
  oninput="if(this.value.length==1)
    document.getElementById('digito-2').focus()">
<input type="text" id="digito-2" maxlength="1">
Correto
<!-- ✓ Usuário controla a navegação -->
<label for="codigo-verificacao">
  Código de verificação (6 dígitos)
</label>
<input type="text" id="codigo-verificacao"
  inputmode="numeric"
  pattern="[0-9]{6}"
  maxlength="6"
  autocomplete="one-time-code"
  aria-describedby="codigo-instrucao">
<p id="codigo-instrucao">
  Digite os 6 dígitos seguidos, sem espaços.
</p>
Dica

Mudanças de foco automáticas são aceitáveis apenas quando o usuário as solicita (ex.: abrir um modal). A abertura de modais deve mover o foco para dentro do modal; o fechamento deve retornar o foco ao elemento que o abriu.

2.4

Não criar armadilhas para o foco do teclado

WCAG A

O usuário deve sempre conseguir sair de qualquer componente usando apenas o teclado (Tab, Shift+Tab ou teclas de seta). A exceção é quando um modal está aberto — o foco deve ficar dentro do modal.

WCAG 2.1.2
Incorreto
<!-- ❌ Modal sem gerenciamento de foco -->
<div class="modal" id="modal">
  <h2>Confirmar exclusão</h2>
  <p>Deseja excluir este registro?</p>
  <button onclick="excluir()">Excluir</button>
  <!-- Tab pode sair do modal para o fundo -->
</div>
Correto
<!-- ✓ Modal com foco gerenciado -->
<dialog id="modal-exclusao"
  aria-modal="true"
  aria-labelledby="modal-titulo">
  <h2 id="modal-titulo">Confirmar exclusão</h2>
  <p>Deseja excluir este registro? Esta ação não pode ser desfeita.</p>
  <div class="acoes-modal">
    <button type="button" onclick="fecharModal()">
      Cancelar
    </button>
    <button type="button" onclick="confirmarExclusao()">
      Excluir
    </button>
  </div>
</dialog>
<!-- Usar dialog nativo ou implementar focus trap via JS -->
Dica

O elemento <dialog> nativo do HTML gerencia foco automaticamente. Para componentes customizados, implemente "focus trap": intercepte Tab e Shift+Tab para manter o foco dentro do modal enquanto aberto.

2.5

Fornecer atalhos de teclado para links, campos e controles importantes

WCAG A

Atalhos de teclado (accesskey) permitem que usuários de teclado e leitores de tela naveguem rapidamente para seções importantes da página.

WCAG 2.1.1
Incorreto
<!-- ❌ Sem atalhos de navegação -->
<nav>
  <a href="#conteudo">Conteúdo</a>
  <a href="#menu">Menu</a>
  <a href="#busca">Busca</a>
</nav>
Correto
<!-- ✓ Atalhos declarados e documentados -->
<div class="barra-acessibilidade">
  <a href="#conteudo-principal" accesskey="1"
    title="Atalho: Alt+1">
    Ir ao conteúdo [1]
  </a>
  <a href="#menu-principal" accesskey="2"
    title="Atalho: Alt+2">
    Ir ao menu [2]
  </a>
  <a href="#campo-busca" accesskey="3"
    title="Atalho: Alt+3">
    Ir à busca [3]
  </a>
</div>
Dica

O eMAG recomenda os atalhos padrão do governo brasileiro: 1=conteúdo, 2=menu, 3=busca. Documente os atalhos na própria barra de acessibilidade. O comportamento do accesskey varia entre navegadores/SOs.

2.6

Não incluir situações com intermitência de tela

WCAG A

Conteúdo que pisca mais de 3 vezes por segundo pode desencadear crises epilépticas fotossensíveis. Todo conteúdo piscante deve respeitar os limites de frequência.

WCAG 2.3.1
Incorreto
<!-- ❌ GIF animado piscante -->
<img src="alerta-piscando.gif"
  alt="URGENTE — Prazo se encerra hoje!">

<!-- ❌ CSS com flash -->
.alerta { animation: piscar 0.2s infinite; }
Correto
<!-- ✓ Destaque sem intermitência -->
<div class="alerta-urgente" role="alert">
  <strong>Atenção:</strong>
  Prazo para inscrições se encerra hoje às 23h59.
</div>

/* CSS: transição suave, sem flash */
.alerta-urgente {
  background: #fef3cd;
  border-left: 4px solid #f59e0b;
  padding: 1rem;
  animation: fadeIn 0.3s ease;
}
Dica

Use a ferramenta PEAT (Photosensitive Epilepsy Analysis Tool) para verificar vídeos e animações. A regra é: sem flashes acima de 3 Hz que ocupem mais de 25% da tela.

2.7

Assegurar o controle do usuário sobre mudanças de conteúdo

WCAG A

Carrosséis, banners rotativos e conteúdo que se move automaticamente devem ter controles para pausar, parar ou retroceder. Movimento automático por mais de 5 segundos precisa de controle.

WCAG 2.2.2
Incorreto
<!-- ❌ Carrossel sem controles -->
<div class="carrossel" id="banner">
  <div class="slide">Destaque 1</div>
  <div class="slide">Destaque 2</div>
  <!-- Troca automática a cada 5s, sem controle -->
</div>
Correto
<!-- ✓ Carrossel com controles acessíveis -->
<section aria-label="Destaques do Portal"
  aria-roledescription="carrossel">
  <div aria-live="polite" aria-atomic="false">
    <div role="group" aria-label="Slide 1 de 3"
      aria-roledescription="slide">
      Destaque 1
    </div>
  </div>
  <div class="controles-carrossel">
    <button type="button"
      aria-label="Slide anterior">‹</button>
    <button type="button"
      id="btn-pausa"
      aria-label="Pausar rotação automática"
      aria-pressed="false">⏸</button>
    <button type="button"
      aria-label="Próximo slide">›</button>
  </div>
</section>
Dica

O padrão ARIA para carrosséis do W3C APG (w3.org/WAI/ARIA/apg/patterns/carousel) é a referência de implementação. O botão de pausa deve ser o primeiro controle focável após o carrossel.

2.8

Assegurar a visibilidade do foco do teclado

WCAG AA

Todo elemento focável deve ter um indicador visual claro do foco. Remover o outline padrão do navegador sem substituir por alternativa é uma violação grave de acessibilidade.

WCAG 2.4.7
Incorreto
/* ❌ Outline removido sem alternativa */
* { outline: none; }
a:focus { outline: 0; }
button:focus { box-shadow: none; }
Correto
/* ✓ Foco visível e consistente */
:focus-visible {
  outline: 3px solid #0048B6;
  outline-offset: 2px;
  border-radius: 2px;
}

/* Para componentes com background escuro */
.sobre-escuro:focus-visible {
  outline-color: #BFDBFE;
}

/* Nunca remova o outline sem substituição */
button:focus-visible {
  outline: 3px solid #0048B6;
  box-shadow: 0 0 0 6px rgba(0,72,182,0.2);
}
Dica

Use :focus-visible ao invés de :focus para mostrar o indicador apenas para navegação por teclado (não ao clicar com mouse). O indicador de foco deve ter contraste de pelo menos 3:1 contra o fundo.

2.9

Disponibilizar barra de acessibilidade

WCAG A

Sítios governamentais devem ter uma barra de acessibilidade com links de pulo para o conteúdo principal e mecanismos de ajuste como alto contraste e tamanho de fonte.

WCAG 2.4.1
Incorreto
<!-- ❌ Sem barra de acessibilidade -->
<body>
  <header>
    <img src="logo.png" alt="Portal MT">
    <nav>...</nav>
  </header>
Correto
<!-- ✓ Barra de acessibilidade completa -->
<div id="barra-acessibilidade"
  role="navigation"
  aria-label="Barra de acessibilidade">
  <a href="#conteudo-principal" accesskey="1">
    Ir ao conteúdo [1]
  </a>
  <a href="#menu-principal" accesskey="2">
    Ir ao menu [2]
  </a>
  <a href="/mapa-do-site" accesskey="4">
    Mapa do site [4]
  </a>
  <button onclick="altoContraste()"
    aria-pressed="false"
    aria-label="Ativar alto contraste">
    Alto contraste
  </button>
  <button onclick="aumentarFonte()"
    aria-label="Aumentar tamanho da fonte">
    A+
  </button>
  <button onclick="diminuirFonte()"
    aria-label="Diminuir tamanho da fonte">
    A-
  </button>
</div>
Dica

O eMAG define os accesskeys padrão do governo brasileiro: 1=conteúdo, 2=menu, 3=busca, 4=mapa do site. A barra deve ser o primeiro elemento do body, antes do header.