Acessibilidade com CSS
Já entregas layouts, movimento e truques modernos de toolkit. A acessibilidade em CSS é a camada que as pessoas sentem: conseguem ver onde está o foco do teclado? Conseguem ler o texto? Uma animação a girar deixa alguém mal? Esta sessão não é um inventário de HTML (landmarks, alt, ARIA). São os hábitos de estilo que mantêm foco, contraste e movimento utilizáveis.
O foco tem de permanecer visível
Utilizadores de teclado percorrem links e controlos com Tab. Se o anel de foco desaparece, ficam perdidos. Prefere :focus-visible para que cliques de rato fiquem calmos e o foco de teclado fique claro:
:root {
--focus-ring: #2563eb;
}
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
outline: 3px solid var(--focus-ring);
outline-offset: 3px;
}
.text-link:focus:not(:focus-visible) {
outline: none;
}
:focus-visible aponta os casos em que um anel ajuda de verdade (normalmente teclado). Combina-o com um anel de alto contraste e um pouco de outline-offset para o anel não se misturar com as bordas.
Nunca outline: none sem substituição
Remover o outline predefinido só é aceitável quando ofereces um estilo de foco personalizado mais claro. Um *:focus { outline: none; } nu é a armadilha clássica:
/* Bad: keyboard users lose the only cue */
.bad-button:focus {
outline: none;
}
/* Good: custom ring that still shows focus */
.good-button:focus-visible {
outline: none;
box-shadow: 0 0 0 3px #fff, 0 0 0 6px #0f766e;
}
Se desligas o outline do browser, outra coisa tem de marcar o controlo focado — box-shadow, cor de borda, ou um fundo que continue óbvio em qualquer tema.
O contraste é uma escolha CSS
Cores de marca brilham numa prancheta e apagam-se num telemóvel ao sol. Trata os pares primeiro plano / fundo como decisões de acessibilidade, não só decoração:
:root {
--surface: #0f172a;
--text: #f8fafc;
--muted: #cbd5e1;
--accent: #38bdf8;
--accent-text: #0c4a6e;
}
.hero {
background: var(--surface);
color: var(--text);
}
.hero .lede {
color: var(--muted);
}
.hero .cta {
background: var(--accent);
color: var(--accent-text);
font-weight: 700;
}
Procura contraste forte no texto de corpo e nos botões. Cinzentos decorativos podem ficar mais suaves em rótulos secundários, mas a cópia principal e os controlos precisam de se manter legíveis. Verifica os pares com um verificador de contraste antes de publicar uma paleta.
Respeitar o movimento reduzido
Animações e transforms grandes podem causar desconforto. Envolve movimento não essencial em prefers-reduced-motion:
.banner {
transition: transform 0.4s ease, opacity 0.4s ease;
}
.banner.is-shown {
transform: translateY(0);
opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
.banner,
.banner.is-shown {
transition: none;
transform: none;
}
.spinner {
animation: none;
}
}
Quem pede ao SO para reduzir o movimento deve continuar a ver o estado final da UI — só sem a viagem. Mantém mudanças essenciais de opacidade ou layout; retira spins em ciclo e slides grandes.
Alto contraste e forced-colors
Alguns ambientes sobrescrevem a tua paleta (High Contrast do Windows / forced-colors). Suaviza decorações frágeis e mantém bordas reais:
.card {
border: 1px solid #e2e8f0;
background: #fff;
box-shadow: 0 8px 24px rgb(15 23 42 / 12%);
}
@media (forced-colors: active) {
.card {
border: 1px solid CanvasText;
background: Canvas;
box-shadow: none;
color: CanvasText;
}
.card a {
color: LinkText;
}
}
Palavras-chave de cor do sistema como Canvas, CanvasText e LinkText ajudam os controlos a permanecerem visíveis quando é o utilizador — não o guia de marca — quem manda nas cores.
Hábitos do lado CSS
📊 CSS accessibility habits
| Practice | CSS habit | Avoid |
|---|---|---|
| Keep focus findable | :focus-visible + strong ring / shadow |
outline: none with no replacement |
| Readable type | High-contrast text/background tokens | Light grey on white for body copy |
| Kind motion | @media (prefers-reduced-motion: reduce) |
Endless spins for everyone |
| Survive high contrast | Real borders; forced-colors tweaks |
Shadow-only “edges” |
| Reachable controls | Comfortable padding / hit area | Tiny icon-only targets with no focus style |
O HTML continua a ser dono de landmarks, rótulos e texto alt. O CSS decide se, depois de estilizados, esses controlos se mantêm percebíveis.
Skip links e focus-within
Um skip link salta o chrome repetido. Estiliza-o para aparecer no foco. :focus-within também pode destacar um grupo inteiro quando um filho está focado:
.skip-link {
position: absolute;
left: 1rem;
top: -3rem;
padding: 0.5rem 0.75rem;
background: #111827;
color: #fff;
border-radius: 0.375rem;
z-index: 20;
}
.skip-link:focus-visible {
top: 1rem;
outline: 3px solid #fbbf24;
outline-offset: 2px;
}
.nav:focus-within {
box-shadow: inset 0 0 0 2px #2563eb;
}
O skip link fica fora do ecrã até receber foco e depois torna-se óbvio. O anel da nav ajuda quando Tab aterra num link filho dentro da barra.
Experimenta tu
- Adiciona um anel
:focus-visiblea links e botões; percorre a página com Tab e confirma que vês sempre o foco. - Escolhe um par de baixo contraste e corrige-o com texto mais escuro ou uma superfície mais profunda.
- Envolve uma transition ou animation em
prefers-reduced-motion: reducee alterna a definição do SO (ou a emulação do DevTools). - Sob emulação forced-colors, garante que os cartões ainda mostram uma borda real.
- Estiliza um skip link que só aparece no foco de teclado.
Erros comuns
outline: none(ououtline: 0) global sem estilo de foco personalizado- Cores de marca bonitas que falham o contraste no texto de corpo e nos botões principais
- Animações grandes para todos sem porta
prefers-reduced-motion - Esconder um controlo focável só com
opacity: 0enquanto ainda recebe Tab - Tratar esta lição de CSS como substituto completo de HTML semântico e ARIA
Resumo
- Mantém o foco de teclado visível — prefere
:focus-visiblee nunca apagues o outline sem um sinal mais forte - Trata o contraste de cor como requisito para texto e controlos
- Honra
prefers-reduced-motione reforça estilos paraforced-colors - Estiliza skip links e usa
:focus-withinonde um grupo precisa de um sinal partilhado - Seguinte: Resumo CSS e próximos passos (
summary) — fechar o curso antes do mini-projeto
🧠 Teste Seu Conhecimento
Teste Seu Conhecimento
Desafie-se com este questionário interativo e veja o quão bem você entende o tópico
📝 Instruções
- Leia cada pergunta cuidadosamente
- Selecione a melhor resposta para cada pergunta
- Você pode refazer o quiz quantas vezes quiser
- Seu progresso será mostrado no topo