Hierarquia semântica de headings em SPAs
SPAs frequentemente quebram a hierarquia de headings durante navegação client-side. Veja como auditar e corrigir sem mudar o design visual.
O problema que ninguém vê, mas screen readers sentem
Em aplicações multi-página tradicionais, cada novo documento HTML começa com um `<h1>` limpo. Em SPAs, o conteúdo muda dinamicamente, mas a hierarquia de headings muitas vezes não é redefinida — resultando em `<h2>` aparecendo sem `<h1>` pai, ou `<h1>` duplicados na mesma página lógica.
Usuários de screen readers navegam por headings como se fossem uma tabela de conteúdo. Uma hierarquia quebrada é equivalente a um índice onde capítulos não têm seções — confuso e inacessível.
Como auditar a hierarquia atual
A extensão "Headings Map" do Firefox (ou Chrome) gera um outline dos headings da página atual. Execute a auditoria em cada rota da sua SPA. O outline deve ter exatamente um `<h1>` por "página lógica" e níveis em cascata sem pular: h1 → h2 → h3, nunca h1 → h3.
Outra ferramenta útil é o axe DevTools: ele detecta automaticamente hierarquias inválidas e classifica por severidade. Integre o axe ao Cypress ou Playwright para capturar regressões automaticamente.
Atenção
O maior erro: usar headings para controle visual de tamanho de texto. Se você precisa de texto "tamanho h2 visualmente" sem ser um heading semântico, use um `<p>` ou `<span>` com classes CSS. Nunca use heading level para fins estéticos.
Focus management após navegação
Além da hierarquia, SPAs precisam gerenciar o foco do teclado após cada navegação. Quando o usuário clica em um link e o conteúdo muda, o foco permanece no link — não no início do novo conteúdo.
A solução é mover o foco programaticamente para o `<h1>` da nova página (ou um elemento `<main>` com `tabIndex={-1}`) após cada transição de rota. Frameworks como Remix fazem isso automaticamente; no React Router ou router customizado, é responsabilidade do desenvolvedor.
// Após mudança de rota, mova o foco para o título principal
useEffect(() => {
const h1 = document.querySelector('h1')
if (h1) {
h1.setAttribute('tabindex', '-1')
h1.focus()
}
}, [path]) // path da sua solução de routingPortodev Studio
Consultoria e engenharia digital · Ago 2026
Continue lendo
10 min de leitura · Jul 2026
Contraste e design tokens: uma abordagem sistemática
Garantir contraste acessível em escala requer mais que checar pares individualmente — requer um sistema de tokens com contraste embutido na definição.
Ler o artigo7 min de leitura · Out 2026
Quanto custa um site lento (e como descobrir no seu caso)
Lentidão não aparece no extrato, mas aparece no funil: visita que desiste antes de carregar, formulário que não é enviado, anúncio pago que leva a uma tela em branco. Veja como medir o custo no seu site.
Ler o guia8 min de leitura · Out 2026
GEO: como fazer sua empresa aparecer nas respostas do ChatGPT
Cada vez mais gente pergunta a um assistente de IA antes de procurar no Google. GEO é o trabalho para sua empresa ser entendida, lembrada e citada nessas respostas. Veja o que já dá para fazer.
Ler o guiaEsses padrões no seu produto.
Em 30 minutos mapeamos como esses conceitos se aplicam ao contexto do seu projeto real.