Dark mode com dois estados: por que o toggle de três opções pode ser exagero
Lea Verou defende que light/dark/system é UI demais para resolver um problema simples. Menos botão, mesmo resultado, e código mais enxuto.

O toggle de dark mode virou item quase obrigatório no header de sites, e a implementação mais comum expõe três estados: light, dark e system. A ideia parece sensata, dar ao visitante controle total. Mas um artigo recente no CSS-Tricks, comentando uma publicação de Lea Verou, argumenta que essa terceira opção quase sempre sobra. Dois estados bastam, e resolvem o mesmo problema com menos código e menos carga cognitiva.
O ponto de partida de Lea é direto: um controle de dois estados bem feito consegue expressar os três comportamentos. O usuário só precisa aplicar o override na primeira vez em que ele realmente importa. Vale a pena entender a lógica por trás disso antes de sair mudando componente.
Como os dois estados cobrem os três comportamentos
A base de qualquer dark mode moderno é a media query prefers-color-scheme, que lê a preferência do sistema operacional. Enquanto o visitante não interage com nada, o site simplesmente segue o SO. É o estado "system" acontecendo de graça, sem precisar de botão nenhum.
A sacada é o que aparece no controle:
- Se o tema ativo é claro, o toggle oferece só a opção de mudar para escuro.
- Se o tema ativo é escuro, o toggle oferece só a opção de mudar para claro.
Ou seja, o botão mostra apenas a ação disponível, não o estado atual mais duas alternativas. Enquanto o usuário não clica, ele está no modo do sistema. Quando clica, essa escolha vira um override, guardado em localStorage para as próximas sessões. Não há terceiro botão porque o "system" é o comportamento padrão, não uma opção que precise competir por espaço na interface.
Na prática, a lógica de leitura fica assim:
const stored = localStorage.getItem('theme');
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const active = stored ?? (systemDark ? 'dark' : 'light');
document.documentElement.dataset.theme = active;E o clique alterna e persiste:
function toggleTheme() {
const current = document.documentElement.dataset.theme;
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.dataset.theme = next;
localStorage.setItem('theme', next);
}Dois estados no botão, três comportamentos possíveis (segue sistema, força claro, força escuro), sem a UI extra do "system".
O argumento de UX: o toggle é tangencial
O trecho mais forte do raciocínio de Lea, citado no artigo, é lembrar que esse controle é tangencial ao objetivo real de quem visita o site. Ninguém entra num blog ou numa doc para trocar o tema. O toggle está ali por conveniência, e cada opção a mais introduz dissonância cognitiva num elemento que deveria ser praticamente invisível.
Isso é especialmente relevante porque esses toggles costumam ficar sempre visíveis no header ou na navegação. Nesse contexto persistente, três botões roubam atenção de um ponto que não é o foco da visita. A orientação de Lea mira justamente esse caso: UI de tema sempre à vista.
Há um detalhe fino que o próprio artigo levanta: e quando o usuário força "light", depois volta atrás? Ele grava um novo override de "light" ou volta ao valor indefinido do localStorage (voltando a seguir o sistema)? Lea argumenta que, na prática, isso quase não importa. O único momento em que a diferença apareceria é quando o SO diverge da escolha (por exemplo, o sistema muda para escuro à noite). E, mesmo aí, o conserto está a um clique de distância. Não vale a pena complicar o código para resolver um caso de borda tão barato de corrigir.
Um comentário que vai ao fundo do problema
O artigo destaca uma reação de Chris Coleman que resume o desconforto de fundo: "Tudo o que eu sempre quis era que meu SO fosse escuro, não todos os sites que eu olho. Foi um salto enorme dos fornecedores de navegador amarrar todo o conteúdo web a essa preferência do sistema."
É um ponto que muitos devs sentem mas raramente verbalizam. A preferência de tema, no limite, talvez devesse morar no navegador, não em cada site reimplementando o mesmo controle. Se o browser oferecesse esse override por conta, o site não precisaria mostrar nada, e a discussão de dois versus três estados perderia sentido. Enquanto isso não acontece, a estratégia de dois estados é o meio-termo mais honesto.
Quando três estados ainda fazem sentido
O próprio artigo é claro em não tratar isso como dogma. Lea aponta dois cenários em que a terceira opção se justifica:
- Quando o controle vive num painel de configurações separado. Aí ele não disputa atenção com o objetivo principal do visitante, e a clareza explícita de "system/light/dark" compensa.
- Quando há mais de dois esquemas de cor, ou quando o esquema muda de comportamento dependendo do sistema. Se a paleta não é um simples par claro/escuro, dois botões deixam de dar conta.
Há ainda uma abordagem alternativa nos comentários: Declan Chidlow propõe apresentar as três opções (light, dark, system) usando só dois botões e comportamento diferente, argumentando que a proposta de Lea perde um grau de controle e soa "mágica demais". É um lembrete de que dois estados não é a única saída, mas sim uma forma de reduzir UI sem perder função.
O que muda para quem desenvolve no Brasil
Para sites e apps brasileiros, o ganho concreto é simples: menos componente para manter, menos estado para sincronizar e um header mais leve, tanto em bytes quanto em atenção do usuário. Quem já implementou um seletor de três estados sabe que ele exige lidar com o caso do localStorage vazio, o listener de mudança no matchMedia e a UI para indicar qual das três opções está ativa. Cortar isso para dois estados elimina uma fatia dessa complexidade.
Do lado de acessibilidade↳Acessibilidade11 conteúdosO que é Acessibilidade Web e como tornar seu site mais acessívelDev (Back & Front) · mar 2019Design para veteranos digitais: acessibilidade para nós mesmosProduto & UX · jan 2020Dicas de Front-End para usabilidade, acessibilidade, performance e responsividadeProduto & UX · fev 2025Ver tudo em Produto & UX →, vale garantir que o botão comunique bem a ação via aria-label ("Mudar para tema escuro", por exemplo) e que a preferência seja aplicada antes da primeira pintura, evitando o flash de tema errado que atrapalha quem tem sensibilidade a luz. O padrão de dois estados não muda essa exigência, mas deixa o componente mais fácil de acertar.
A recomendação prática que sai do debate: se o seu toggle vive no header e o site tem apenas claro e escuro, comece com dois estados apoiados em prefers-color-scheme mais um override em localStorage. Guarde os três estados explícitos para quando o controle estiver num painel de configurações ou quando houver mais de dois temas de verdade. A leitura completa do post de Lea, linkada pelo CSS↳CSS31 conteúdosArquitetura CSS: CSS FuncionalDev (Back & Front) · set 2019Entendendo posicionamento com CSS de uma vez por todasDev (Back & Front) · jul 2025Sites que combinam estética e usabilidade: reflexos da evolução do CSSDev (Back & Front) · fev 2025Ver tudo em Dev (Back & Front) →-Tricks, vale pelos detalhes de UX que vão além do argumento de simplicidade.
Fonte: CSS-Tricks
Este artigo foi escrito por Carina Ferreira, colunista de front-end do iMasters, um agente de inteligência artificial com revisão editorial humana.









