# Acessibilidade e CSS

> Crie layouts acessíveis com CSS moderno. Aprenda técnicas essenciais de visibilidade de foco, contraste de cores e design inclusivo conforme WCAG.

URL: https://dpw.dev/acessibilidade/acessibilidade-css/  
Publicado em: 2021-10-25  
Categoria: acessibilidade  
Autor: Tárcio Zemel

**Acessibilidade** (a11y) é uma habilidade crítica para desenvolvedores trabalhando com qualquer stack de tecnologia. Especificamente no front-end, **CSS moderno** fornece recursos que podemos aproveitar para tornar os layouts mais acessíveis e inclusivos para pessoas de todas os níveis de habilidades, em qualquer tipo de dispositivo.

## O que significa "acessível"?

[Sites acessíveis](/tag/acessibilidade/) são aqueles criados sem barreiras para que pessoas de vários níveis de habilidades acessem o conteúdo ou executem ações. Um padrão aceito internacionalmente, denominado [Web Content Accessibility Guidelines](https://www.w3.org/WAI/standards-guidelines/wcag/) (**WCAG**) fornece critérios de sucesso para ajudar a orientar na criação de experiências acessíveis.

Alguns exemplos de **barreiras comuns de acessibilidade** são:

- Incapacidade de ver o conteúdo ou distinguir elementos da interface devido a baixo contraste de cores;
- Acesso reduzido ou removido a conteúdo não textual, como imagens ou gráficos, devido a falhas em fornecer textos alternativos;
- Pessoas que usam primariamente o teclado "presas" no site devido a não gerenciamento do foco para elementos interativos;
- Determinados tipos de movimentos e animações causando dores de cabeça (ou pior) em pessoas com distúrbios vestibulares;
- Impedimento de pessoas que usam tecnologias assistivas, como leitores de tela, executarem ações devido à falha em desenvolver controles personalizados acomodarem padrões esperados;
- Limitação dos métodos de navegação de tecnologias assistivas comuns devido ao não uso de HTML semântico, incluindo hierarquia de títulos e elementos de referência (_landmark elements_).

Os [Critérios de Sucesso](https://www.w3.org/WAI/WCAG22/Understanding/understanding-techniques) (_Success Criteria_) "são projetados para serem amplamente aplicáveis às tecnologias da Web atuais e futuras, incluindo aplicativos dinâmicos, celular, televisão digital etc.".

A seguir, veja a análise de alguns critérios de sucesso e como o CSS moderno ajuda a fornecer soluções acessíveis.

## Visibilidade do foco (Focus visibility)

Uma violação de CSS dos critérios de acessibilidade muito comum é remover `:focus` em links, botões e outros controles interativos. Sem fornecer uma alternativa ao estilo de `:focus`, isso é imediatamente uma violação do [Critério de Sucesso 2.4.11 das WCAG: Aparência de Foco](https://www.w3.org/WAI/WCAG22/Understanding/focus-appearance-minimum.html) (_Focus Appearance_).

Comumente, a razão pela qual ele é removido é devido à sensação de que o estilo nativo do navegador não é atraente ou não se encaixa nas opções de design do meta. Mas, com CSS moderno, surge uma nova propriedade que pode ajudar a tornar os contornos mais atraentes.

Ao usar `outline-offset`, é possível fornecer um valor positivo para posicionar o contorno longe do elemento. Para o deslocamento (_offset_), usa-se a [unidade CSS](/css/unidades-css-rem-vh-vw-vmin-vmax-ex-ch/) `em` para posicionar o contorno em relação ao elemento com base no `font-size`.

```scss
button:focus {
  outline: max(1px, 0.1em) solid currentColor;
  outline-offset: 0.25em;
}
```

Como alternativa, é possível definir o `outline-offset` usando um valor negativo para inserir o contorno do perímetro do elemento.

```scss
button:focus {
  outline: max(1px, 0.1em) dashed currentColor;
  outline-offset: -0.25em;
}
```

Há, também, uma nova pseudo-classe que pode ter o uso considerado em algumas circunstâncias para melhorar bastante a questão de acessibilidade com CSS.

A pseudo-classe `:focus-visible` exibirá um outline (ou outro estilo definido) somente quando o dispositivo/navegador (_user agent_) determinar que ele precisa estar visível. Normalmente, isso significa que ele aparecerá para usuários de teclado na interação com a tecla de tabulação, mas não para quem usa mouse.

Fazendo essa atualização no snippet, os estilos de botão provavelmente só serão exibidos quando ocorrer o foco através da tecla Tab:

```
button:focus {
  outline: none;
}

button:focus-visible {
  outline: max(1px, 0.1em) dashed currentColor;
  outline-offset: -0.25em;
}
```

O [suporte a `:focus-visible`](https://caniuse.com/css-focus-visible), apesar de já bem decente, ainda não é total (na data da publicação deste artigo), então, para uma abordagem _progressive enhancement_, é possível usar:

```
button:focus {
  outline: max(1px, 0.1em) dashed currentColor;
  outline-offset: -0.25em;
}

button:focus:not(:focus-visible) {
  outline: none;
}

button:focus-visible {
  outline: max(1px, 0.1em) dashed currentColor;
  outline-offset: -0.25em;
}
```

## Foco vs. Source Order

Outro critério importante de **CSS para acessibilidade**, relacionado com foco é o [Critério de Sucesso 2.4.3: Ordem do Foco](https://www.w3.org/WAI/WCAG21/Understanding/focus-order). Para usuários visuais e não visuais, a ordem do foco -- que, normalmente, é iniciada pela tabulação do teclado -- deve prosseguir logicamente.

Particularmente, para usuários visuais, a ordem do foco deve seguir um caminho esperado, o que geralmente significa seguir a ordem da fonte (_source order_).

Como consta na documentação citada:

> Por exemplo, um usuário de leitor de tela interage com a ordem de leitura determinada de maneira programática, enquanto um usuário de teclado com visão interage com a apresentação visual da página Web. Deve-se tomar cuidado para que a ordem do foco faça sentido para ambos os conjuntos de usuários e não pareça, para nenhum deles, alternar aleatoriamente.

CSS moderno oferece propriedades de layout (CSS Grid, Flexbox) para reorganizar a ordem visual (_visual order_) em algo diferente da ordem de origem (_source order_). O impacto disso é potencialmente falhar no critério de sucesso da ordem de foco se houver elementos focalizáveis que estão sendo reorganizados em uma ordem surpreendente.

A ideia ao comentar sobre isso é mais fornecer consciência desse critério ao considerar como resolver determinados desafios de layout.

Como adendo, leia o artigo de **Manuel Matuzovic** tem um [guia excelente com considerações de layout de CSS Grid e alteração da ordem de origem](https://www.matuzo.at/blog/the-dark-side-of-the-grid-part-2/).

## Desktop Zoom e Reflow

Comumente, devs testamos vários tamanhos de viewport usando ferramentas de desenvolvimento de navegador (DevTools), bem como em dispositivos móveis reais, e ficamos satisfeitos com o comportamento responsivo do projeto.

Mas, provavelmente, você está perdendo um ponto de teste: zoom da área de trabalho (_desktop zoom_).

Segundo o [Critério de Sucesso das WCAG 1.4.10: Reflow](https://www.w3.org/WAI/WCAG22/Understanding/reflow.html):

> Reflow é o termo usado para oferecer suporte a zoom da área de trabalho de até 400%. Em uma resolução de 1280px de largura a 400%, o conteúdo da viewport é equivalente a 320 pixels CSS de largura. A intenção de um usuário com esta configuração é acionar o conteúdo para refluir em uma única coluna para facilitar a leitura.

Normalmente, o zoom começa a acionar o comportamento responsivo definido através de media queries. Mas, atualmente, não há media queries de zoom. Consequentemente, a proporção da imagem de uma área de trabalho com zoom de 400% pode causar problemas de reflow no conteúdo.

Alguns exemplos de possíveis problemas:

- Navegação sticky que cobre metade (ou mais) da viewport;
- Resultados indesejados ao usar técnicas de tipografia fluida;
- Problemas de overflow ou overlap que cortam o conteúdo;
- Espaçamento de `margin` e `padding` parecendo muito grandes em relação ao tamanho do conteúdo;
- etc.

Sem uma media query de zoom, pode ser difícil conceber soluções de zoom que sejam independentes das suposições de tamanho da viewport.

No entanto, com funções CSS modernas como `min()` e `max()`, há maneiras de resolver algumas questões de zoom sem prejudicar a intenção original do planejamento mobile.

Para um exemplo prático, veja a situação de controle de espaço vertical. Uma prática comum é os designers criarem um "escala" (_pixel ramp_) para espaçamento, talvez com base em uma unidade de 8 pixels. Então, podem surgir utilitários de espaçamento semelhantes a:

```scss
.margin-top-xs {
  margin-top: 8px;
}

.margin-top-sm {
  margin-top: 16px;
}

.margin-top-md {
  margin-top: 32px;
}

.margin-top-lg {
  margin-top: 64px;
}

.margin-top-xl {
  margin-top: 128px;
}
```

E assim por diante, para acomodar toda a extensão da "rampa". Isso, geralmente, funciona em uma variedade padrão de dispositivos, mas considere que o valor `xl` (`128px`) em uma área de trabalho com zoom de 400% torna-se a metade da altura da viewport!

Em vez disso, é possível atualizar a extremidade superior do intervalo com `min()` para selecionar o menor valor calculado. Isso significa que, para janelas de exibição sem zoom, `128px` será usado e, para viewports com zoom de 400%, um valor de unidade de viewport alternativo pode ser usado:

```
margin-top: min(128px, 15vh);
```

## Tamanho de alvos interativos (Sizing Interactive Targets)

Também é importante considerar o tamanho adequado de alvos interativos, em que o termo "alvo" vem do [Critério de Sucesso 2.5.5: Tamanho do Alvo](https://www.w3.org/WAI/WCAG22/Understanding/target-size.html):

> A intenção deste critério de sucesso é garantir que os tamanhos de alvo sejam grandes o suficiente para que os usuários os ativem facilmente, mesmo se o usuário estiver acessando o conteúdo em um pequeno dispositivo portátil com tela de toque, tiver destreza limitada ou tiver problemas para ativar pequenos alvos por outros motivos . Por exemplo, mouses e dispositivos apontadores semelhantes podem ser difíceis de usar para esses usuários, e um alvo maior os ajudará a ativar o alvo.

Apresentado nas WCAG 2.2 está o [Critério de Sucesso 2.5.8: Espaçamento do Alvo do Indicador](https://www.w3.org/WAI/WCAG22/Understanding/pointer-target-spacing.html). Juntos, a orientação indica que os controles geralmente interativos devem:

- Ter um tamanho mínimo de 44 px; ou
- Permitido um tamanho mínimo (incluindo o espaçamento entre o controle e outros elementos) de 44px.

É bastante comum ter que alternar tipos de interação com base no tipo de dispositivo usado. Pode ser bastante útil saber [como detectar touch com CSS puro](/css/como-detectar-touch-com-css-puro/).

## Movimento (Motion) Reduzido

Sabia que algumas pessoas podem ter distúrbios vestibulares e correr o risco de dores de cabeça, náusea ou até convulsões devido ao movimento e animações piscando?

Existem 3 critérios principais:

- [Critério de Sucesso 2.3.1: Três flashes ou abaixo do limite](https://www.w3.org/WAI/WCAG22/Understanding/three-flashes-or-below-threshold.html). As páginas da Web não contêm nada que pisque mais do que 3 vezes em qualquer período de 1 segundo, ou o flash está abaixo dos limites gerais de flash vermelho;
- [Critério de Sucesso 2.3.2: Três Flashes](https://www.w3.org/WAI/WCAG22/Understanding/three-flashes). Páginas da Web não contêm nada que pisque mais de 3 vezes em qualquer período de 1 segundo;
- [Critério de Sucesso 2.3.3: Animação de Interações](https://www.w3.org/WAI/WCAG22/Understanding/animation-from-interactions). A animação de movimento acionada pela interação pode ser desativada, a menos que a animação seja essencial para a funcionalidade ou a informação que está sendo transmitida.

CSS moderno oferece uma media feature que pode ser usada para testar a preferência definida pelo sistema operacional do usuário sobre o movimento. Embora suas animações/transições de base devam atender aos limites relacionados ao flash conforme observado nos critérios WCAG, é possível evitá-los totalmente se um usuário preferir movimento reduzido.

Aqui está uma regra rápida definida para lidar globalmente com isso, cortesia do [Modern CSS Reset](https://piccalil.li/blog/a-modern-css-reset):

```scss
/* Remove todas as animações e transições
para pessoas que preferem não vê-los */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
```

As animações são executadas uma vez e todas as transições acontecerão instantaneamente. Em alguns casos, você desejará planejar animações para essa possibilidade para garantir que elas "congelem" no quadro desejado.

É possível testar os resultados dessa media feature no Chrome, abrindo as DevTools e selecionando o menu kebab (3 pontos verticais), depois em "Mais ferramentas" e "Renderização". Em seguida, você pode alternar as configurações na seção "Emular o recurso de mídia CSS prefere movimento reduzido".

![Acessibilidade e CSS: printscreen das DevTools do Chrome com configuração da media feature prefers-reduced-motion.](/images/blog/acessibilidade-css/chrome-prefers-reduced-motion.webp)

## Cor e contraste

[Dark mode](/css/dark-mode-css-facil/) parece uma moda passageira, mas para alguns usuários é essencial para garantir que eles possam ler seu conteúdo. Embora, atualmente, não haja diretrizes instruindo que os modos escuro e claro para o conteúdo sejam necessários, é possível começar a se preocupar com o futuro considerando a oferta de ambos os modos.

O que é um requisito é que, se você oferecer o modo escuro, continue a passar pelo menos nas diretrizes de contraste de cor padrão disponíveis no [Critério de Sucesso 1.4.3: Contraste (Mínimo)](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum).

As taxas de contraste mínimas a serem atendidas são de, pelo menos:

- 4.5:1 para texto normal;
- 3:1 para texto grande -- definido como 18.66px e negrito ou maior, ou 24px e maior;
- 3:1 para gráficos e componentes de interface do usuário (como bordas de inputs formulário).

Independentemente de você fornecer ou não o modo claro e escuro, os usuários de dispositivos Windows 10 podem selecionar uma configuração do sistema para [habilitar o Modo de Alto Contraste](https://support.microsoft.com/en-us/windows/use-high-contrast-mode-in-windows-10-fedc744c-90ac-69df-aed5-c8a90125e696) (High Contrast Mode).

Na maioria dos casos, você deve permitir que as configurações do usuário neste modo sejam aplicadas. Ocasionalmente, a aplicação das configurações de alto contraste significa que as cores que são importantes para a compreensão da sua interface serão removidas.

Existe uma [lista completa de propriedades afetadas por este modo de "cor forçada"](https://www.w3.org/TR/css-color-adjust-1/#forced-colors-properties), mas 3 propriedades frequentemente críticas que geralmente serão removidas no Modo de alto contraste do Windows são:

- `box-shadow`;
- `background-color`;
- `background-image` a menos que haja um valor `url()`.

E 2 propriedades críticas que terão suas cores trocadas pelo equivalente da "cor do sistema" (_system color_):

- `color`
- `border-color`

Às vezes, essas propriedades podem ser compensadas usando alternativas transparentes. Por exemplo, se você estiver usando `box-shadow` como uma alternativa para o `outline` a fim de combinar o `border-radius` em `:focus`, ainda é preciso incluir um `outline` com o valor de cor definido como `transparent` como o complemento para manter o estilo `:focus` para forçado modos de cor.

Se você estiver usando ícones SVG, passar `currentColor` como o valor de `fill` ou `stroke` ajudará a garantir que eles respondam às configurações de cores forçadas.

## Conclusão

Apesar de parecer que não, acessibilidade e CSS (**a11y+CSS**) podem andar juntos para prover experiências excelentes de uso para todos os visitantes de um projeto Web.

[Acessibilidade na Web](/tag/acessibilidade/) ainda é bastante negligenciada, especialmente, aqui, no Brasil. Cabe a nós, desenvolvedores, estudarmos sobre o assunto para conseguirmos avaliar melhor os impactos de implementações acessíveis para os projetos.

Os tópicos deste artigo clareiam muita coisa sobre **CSS e acessibilidade** e como eles podem (e devem) andar juntos.

---

Fonte: [dpw - desenvolvimento para web](https://dpw.dev/) (pt-BR).
Guia para agentes: https://dpw.dev/llms.txt
Índice completo: https://dpw.dev/sitemap-index.xml
Feed: https://dpw.dev/rss.xml
