Transições suaves de modo claro e escuro: tokens, CSS e movimento
Como construir uma opção de tema claro/escuro que respeite a configuração do sistema, evite flash durante o carregamento, estilize controles nativos e anime sem prejudicar a acessibilidade.
Ponto principal
Crie temas em tokens semânticos, siga a configuração do sistema com prefere-color-scheme por padrão, deixe as pessoas substituí-lo e defina a propriedade color-scheme para que os controles de formulário e as barras de rolagem correspondam. Aplique o tema salvo antes da página ser renderizada para evitar flash. Mantenha a animação da mudança curta, como um cross-fade rápido ou uma transição de visualização, e pule-a quando o movimento reduzido estiver ativado.
Comece pela configuração do sistema
O recurso de mídia com esquema de cores prefere informa se o usuário solicitou ao sistema operacional um tema claro ou escuro. Use-o como padrão e adicione uma opção no aplicativo que o substitua e seja lembrado.
Tema com tokens, não substituições
Defina cores como tokens semânticos (superfície, texto, borda, acento) e atribua a cada tema seus próprios valores, geralmente como propriedades personalizadas CSS no elemento raiz. Os componentes nunca mudam entre os temas; apenas os valores do token o fazem. Esta é a mesma abordagem de token de três níveis usada para sistemas de design multimarcas.
Não se esqueça dos controles nativos
MDN explica que a propriedade color-scheme informa ao navegador quais esquemas um elemento suporta, o que altera as cores padrão dos controles de formulário, barras de rolagem e outras UI integradas. Sem ele, uma página escura pode mostrar entradas e barras de rolagem em branco brilhante.
Evite o flash durante a carga
Se o tema salvo for aplicado por JavaScript após a renderização da página, as pessoas verão um flash do tema errado. Aplique-o o mais cedo possível, com um pequeno script embutido no cabeçalho do documento ou um atributo renderizado pelo servidor, antes que a folha de estilo seja exibida.
Anime o switch com cuidado
Um curto cross-fade, em torno de 150 a 250 milissegundos, faz com que a mudança pareça deliberada. Evite fazer a transição de todas as propriedades de cores em todos os elementos, o que pode ser lento em páginas grandes; um único instantâneo de transição de visualização geralmente é mais suave. Deixe a alternância clara, com um rótulo ou dica de ferramenta, e remova a animação quando o movimento reduzido estiver ativado.
Trecho de implementação em produção
/* Tokens per theme */
:root { color-scheme: light dark; --surface: #ffffff; --text: #121212; }
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) { --surface: #121212; --text: #f2f2f2; }
}
:root[data-theme="dark"] { color-scheme: dark; --surface: #121212; --text: #f2f2f2; }
:root[data-theme="light"] { color-scheme: light; }
body { background: var(--surface); color: var(--text); }
// Switch with a View Transition where supported, instantly otherwise
function setTheme(theme) {
const apply = () => { document.documentElement.dataset.theme = theme; localStorage.setItem('theme', theme); };
const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!document.startViewTransition || reduce) return apply();
document.startViewTransition(apply);
}Princípios-chave para lembrar
- O padrão é o esquema de cores preferido; deixe as pessoas substituirem e lembrarem disso
- Tema com tokens semânticos, não substituições por componente
- Defina o esquema de cores para que os controles nativos correspondam
- Aplique o tema salvo antes de pintar pela primeira vez
- Mantenha a animação do switch curta e respeite o movimento reduzido
Perguntas frequentes
Fontes
- prefers-color-scheme — Documentos da Web MDN
- color-scheme — Documentos da Web MDN
- View Transition API — Documentos da Web MDN