CategoriaDesign de produto
Modo escuro não é inverter cor: contraste na prática
Modo escuro não é inversão de cor. É uma segunda escolha da escala de contraste, feita com os mesmos tokens e valores diferentes. Um tema gerado ao virar os valores do tema claro mantém a hierarquia antiga e perde a separação entre camadas. Por isso a inversão automática costuma reprovar na WCAG 2.2.
Por que a inversão quebra a hierarquia
A razão de contraste mede uma relação entre duas cores. Ela não mede o lugar da cor na interface.
No tema claro a página é a superfície mais clara. O cartão fica acima dela com um valor pouco diferente, e o diálogo fica acima do cartão. A ordem das superfícies carrega o significado.
Virar os valores espelha essa ordem. O cartão que parecia elevado passa a parecer rebaixado, porque a superfície atrás dele é mais escura que ele mesmo. A razão entre as duas cores pode continuar igual enquanto o significado do par muda.
Hierarquia é relação entre superfícies. A inversão move valores, não relações.
O que a WCAG 2.2 exige
As Diretrizes de Acessibilidade para Conteúdo Web na versão 2.2 declaram três limites de contraste. Cada um vale para um tipo de conteúdo.
- O Critério de Sucesso 1.4.3 (em inglês), nível AA, exige razão de contraste de no mínimo 4,5 para 1 em texto e em imagens de texto.
- O mesmo critério (em inglês) baixa a exigência para 3 para 1 em texto de escala grande. O glossário define escala grande como no mínimo 18 pontos, ou 14 pontos em negrito.
- O Critério de Sucesso 1.4.11 (em inglês), nível AA, exige 3 para 1 contra as cores adjacentes em componentes de interface e objetos gráficos.
- O Critério de Sucesso 1.4.6 (em inglês), nível AAA, sobe a exigência de texto para 7 para 1 e mantém 4,5 para 1 em texto grande.
O documento de entendimento do 1.4.3 (em inglês) traz a conversão. Um ponto equivale a 1,333 pixel CSS, então 14 pontos são cerca de 18,5 pixels e 18 pontos são cerca de 24 pixels.
Dois detalhes decidem a maioria das falhas. Os limites não são arredondados, e 4,499 para 1 não atende a 4,5 para 1. E um componente sem texto e sem ícone precisa de borda visível em 3 para 1, porque a borda passa a ser o único sinal de que o controle existe (WCAG 1.4.3 (em inglês), WCAG 1.4.11 (em inglês)).
Como medir contraste
A razão de contraste é (L1 + 0,05) / (L2 + 0,05), em que L1 é a luminância relativa da cor mais clara e L2 é a da mais escura. O glossário registra que o resultado vai de 1 para 1 até 21 para 1.
Luminância não é a média dos canais RGB. Ferramenta que tira média dos canais informa um número que a WCAG não usa.
O documento de entendimento (em inglês) pede que o autor leia as cores do markup ou das folhas de estilo, não da tela renderizada. O antialiasing faz texto fino e linha fina renderizarem mais apagados que a cor declarada.
Essa nota traz um aviso prático. Uma fonte fina pode passar no cálculo e ainda assim ser difícil de ler. O documento recomenda fonte mais pesada, ou um par de cores que supere o limite.
Em gradiente ou foto atrás de texto, a orientação é testar a área de menor contraste, não a média. O esquema de cor do guia do Material Design e o contraste dentro dele são o tema de cor e papel de cor.
Por que sombra não separa camada no escuro
A sombra funciona escurecendo uma superfície em relação à superfície atrás dela. No fundo escuro sobra pouco espaço para escurecer, então a sombra perde a função.
Quem faz esse trabalho passa a ser o valor do próprio fundo. No tema escuro uma camada fica acima da página quando o fundo dela é mais claro que a página, e abaixo quando é mais escuro. Elevação vira escala de claridade, não escala de sombra.
Essa escala tem limite. Perto do preto, dois passos de claridade são difíceis de distinguir, então um tema que começa no preto puro acaba o espaço depois de uma ou duas camadas.
O Carbon (em inglês), sistema de design da IBM, documenta isso como modelo de camadas (em inglês). Os temas dele pareiam um tema claro, White ou Gray 10, com um tema escuro, Gray 100 ou Gray 90. As camadas têm nome de posição, não de valor de cor.
Bordas e contornos carregam parte do trabalho. No escuro, uma borda fina em 3 para 1 contra as duas superfícies substitui a sombra que separava o cartão no tema claro (WCAG 1.4.11 (em inglês)).
Token de cor contra valor solto
Token de cor nomeia um papel. Valor solto nomeia uma cor. A diferença decide quanto custa mudar o tema.
O Carbon (em inglês) declara a regra em uma linha. Não dá para implementar modo claro e escuro sem usar tokens de cor em todo o produto, e valor fixo não muda quando o modo troca.
O token também carrega a verificação. Quando o fundo do botão é um token, o build lê o par de tokens e calcula a razão. Quando o fundo é um literal, a conferência precisa de olho humano e captura de tela.
O teste prático é rápido. Procure valores hexadecimais fora do arquivo de tokens. Cada um encontrado é um ponto onde o tema escuro pode falhar em silêncio.
O token precisa de um nome que sobreviva à troca de tema. Um token chamado cinza-claro deixa de significar algo no tema escuro. Um token chamado superfície-elevada mantém o sentido nos dois.
Como testar contraste no build
A conferência de contraste pertence ao build, ao lado do lint e da checagem de tipos. Revisão manual pega só as telas que alguém lembrou de abrir.
A checagem precisa de três entradas. Precisa dos pares de tokens em uso, do fundo atrás de cada cor de texto, e do tamanho e do peso do texto. O tamanho decide qual limite vale, já que texto grande cai de 4,5 para 1 para 3 para 1 (WCAG 1.4.3 (em inglês)).
O resultado é uma lista, não um sim ou não. A lista deve nomear o par de tokens, a razão calculada, o limite e o arquivo que usa o par.
Duas regras mantêm a checagem correta. Não arredonde a razão antes de comparar, porque a orientação trata 4,499 para 1 como falha. E resolva o fundo real, porque texto sobre cartão sobre página tem dois candidatos e o mais rígido vence (WCAG 1.4.3 (em inglês)).
Checagem que lê tokens cobre a troca de tema. Checagem que lê captura de tela cobre um tema e um tamanho de tela.
A ferramenta é secundária. Qualquer script que converta os valores de token em luminância e aplique a fórmula serve, e a fórmula é pública.
Foco e estado desabilitado, onde o contraste escapa
O foco é o estado em que o contraste mais se perde, porque o indicador vive na fronteira entre duas superfícies.
O Critério de Sucesso 1.4.11 cobre esse caso. Toda informação visual necessária para indicar estado, como selecionado ou focado, precisa de 3 para 1 contra as cores adjacentes (WCAG 1.4.11 (em inglês)).
O Critério de Sucesso 2.4.13 (em inglês), nível AAA, acrescenta uma medida. O indicador de foco precisa cobrir ao menos a área de um perímetro de 2 pixels CSS do componente sem foco. O contraste entre o estado com foco e o sem foco precisa chegar a 3 para 1.
A regra das cores adjacentes decide o caso difícil. Anel de foco dentro do cartão precisa contrastar com o cartão, e anel fora precisa contrastar com a página. Anel desenhado na fronteira pode reprovar nos dois.
O estado desabilitado é a outra saída, e vem com exceção escrita. Os critérios 1.4.3 e 1.4.11 dispensam componentes de interface inativos, então um controle cinza não tem exigência de contraste.
A exceção não é instrução de design. Um controle desabilitado ilegível deixa a pessoa sem saber qual ação está bloqueada, e o documento de entendimento (em inglês) registra que controle de baixo contraste pode passar despercebido.
Uma regra que funciona é apagar o controle desabilitado menos do que dá vontade, e manter o rótulo acima da razão de um texto de corpo. A exceção remove a obrigação, não o custo.
Onde o modo escuro piora, e quando o claro ganha
Modo escuro não vem de graça. O custo está documentado.
O Carbon (em inglês) registra que o modo escuro é melhor para pessoas com catarata e transtornos relacionados, e que emite menos luz, o que pode reduzir fadiga ocular e dor de cabeça. A mesma página (em inglês) registra que parte da pesquisa mostra usuários sem deficiência visual indo melhor no modo claro.
Texto longo é o ponto fraco. Uma página de corpo de texto em cor clara sobre fundo escuro é mais difícil de ler que o mesmo texto no tema claro. Peso de fonte fino piora o quadro.
O tema claro é a escolha certa para leitura longa, para documentação, para formulário com muitos campos e para qualquer superfície que a pessoa encara por uma hora. O modo escuro serve para sessões curtas, mídia, código e interface usada à noite.
Muitas vezes a melhor resposta é não escolher. Quando os dois temas compartilham o conjunto de tokens e ambos passam na checagem, a pessoa decide por preferência e o build protege os dois lados.
Onde o Nielsen Norman Group discorda
Os três textos do Nielsen Norman Group não contam a mesma história, e vale mostrar onde eles se separam.
O texto sobre modo escuro (em inglês) revisa a literatura e relata que a polaridade negativa atrapalha principalmente quem tem visão normal. O texto sobre os problemas relatados por quem usa modo escuro (em inglês) vai além em outra direção. Ele afirma que o efeito é muito menor do que se alega. Parte da pesquisa não encontrou diferença significativa em cansaço visual e dor de cabeça, e a luz do ambiente pesou tanto quanto a cor. Os dois textos medem o mesmo tema e chegam a tamanhos de efeito diferentes.
Os outros dois textos não são sobre modo nenhum. O texto sobre baixo contraste (em inglês) é de 2015 e manda aumentar o tamanho da fonte antes de baixar o contraste. O texto sobre legibilidade (em inglês) manda manter alto contraste entre caractere e fundo. Os dois convergem contra o texto apagado, inclusive o apagado do modo claro.
A posição deste post é a mais estreita. Ele mantém a razão como régua testável e trata o modo como segunda escala, e não afirma que uma polaridade ganha para todo mundo.
Fontes
- W3C, Understanding Success Criterion 1.4.3: Contrast (Minimum) (em inglês)
- W3C, Understanding Success Criterion 1.4.6: Contrast (Enhanced) (em inglês)
- W3C, Understanding Success Criterion 1.4.11: Non-text Contrast (em inglês)
- W3C, Understanding Success Criterion 2.4.13: Focus Appearance (em inglês)
- W3C, Web Content Accessibility Guidelines (WCAG) 2.2
- IBM, Carbon Design System, Color usage (em inglês)
- Nielsen Norman Group, Dark Mode (em inglês)
- Nielsen Norman Group, Dark Mode Users’ Issues (em inglês)
- Nielsen Norman Group, Low-Contrast Text (em inglês)
- Nielsen Norman Group, Legibility, Readability, and Comprehension (em inglês)
Como verificar antes de publicar
- Calcule a razão de cada par de tokens de texto e compare com o limite do tamanho, sem arredondar.
- Confira cada anel de foco contra as duas superfícies adjacentes, dentro do cartão e fora dele.
- Leia o controle desabilitado com o braço esticado e decida se o rótulo ainda diz qual ação está bloqueada.
- Confirme que nenhuma sombra carrega a separação sozinha, e que borda ou passo de claridade a substitui.
- Procure nos estilos valores hexadecimais que passam longe do arquivo de tokens e mova cada um para token.
- Troque o tema com a checagem rodando e confirme que os dois temas informam valores diferentes para os mesmos tokens.
- Teste a área de menor contraste de qualquer gradiente ou imagem atrás de texto, não a média.
- Rode a checagem no build, para uma cor fixa nova falhar antes de chegar a uma pessoa.
Tema escuro que passa na mesma checagem do tema claro é uma segunda escala, não um filtro. Construa a escala com tokens, meça no build e deixe a pessoa escolher o lado.


