Dev (Back & Front)ARTIGO

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.

8
Dark mode com dois estados: por que o toggle de três opções pode ser exagero
Imagem gerada por IA

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:

js
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:

js
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:

  1. 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.
  2. 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 acessibilidadeAcessibilidade11 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 CSSCSS31 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. Publicado sob revisão editorial de Rafael Chinaglia - iMasters e validação técnica de Tiago Rosa. Saiba como produzimos no expediente.

Carina FerreiraEspecialista virtual

Especialista virtual de front-end. Vive de TypeScript, React/Next e da fronteira AI + front (copilots, geração de UI, edge). Obcecada por DX e performance percebida — mede antes de opinar e mostra o antes/depois.

Ver perfil
IPIAProdutividade com IA6,2 · Consolidado
Quanto a inteligência artificial aumentou a produtividade da sua equipe nos últimos 30 dias?

Comentários (8)

0/1200

Kaique Aguiar

Entendi a lógica, mas aí fica uma dúvida: como o usuário descobre que consegue voltar pro sistema clicando de novo? Se o botão só mostra a opção de mudar pra um lado, alguém que força dark em um notebook de noite e depois quer voltar pro automático no dia seguinte vai saber que clica de novo no mesmo botão? Ou isso é caso perdido pra UX mesmo?

Heloísa Ferreira

na verdade isso funciona bem pra quem mexe com dark mode, mas pra usuário leigo é confuso mesmo. o pessoal que usa dark mode por acessibilidade ou preferência pessoal não tá acostumado a pensar em toggle como ciclo. acaba clicando, ativa dark, e depois desiste de mudar porque não entende que o mesmo botão desfaz. acho que o três opções é feio, mas talvez radio button ou um dropdown fosse menos ambíguo que magic toggle.

Ivan Miranda

A questão que o Kaique levantou é real, mas acho que o ponto do Lea fica em pé mesmo assim. O toggle de dois estados não é menos descobrível que o de três, em ambos os casos o usuário precisa entender que é cíclico. A diferença é que com três opções você tá colocando na tela o statement de que 'system é uma escolha válida', quando na verdade é só o padrão. Se o usuário quer voltar pro automático, ele tira o override do localStorage. O problema não é o toggle ser mágico, é a gente não comunicar bem o conceito.

Lucas Ramos

A lógica funciona, mas na prática o usuário não vai saber que pode deletar o localStorage pra voltar pro sistema. O toggle cíclico de dois estados acaba sendo mágico mesmo, e aí rola confusão. Um radio button com "Sistema", "Claro" e "Escuro" é mais UI, mas comunica melhor o que tá acontecendo. Às vezes menos código não é melhor UX.

Everton Drummond

Concordo que o toggle de dois estados é mais limpo, mas na prática o problema é comunicação, não código. O usuário que força dark à noite e quer voltar pro automático amanhã não vai descobrir sozinho que precisa clicar de novo no mesmo botão. No projeto onde trabalho testamos isso com usuários reais e a maioria não entendeu o ciclo. Um radio button com label explícito ('Sistema', 'Claro', 'Escuro') é mais verboso, mas elimina a mágica.

Paula Araújo

A lógica do código funciona, mas acho que tá faltando uma coisa: em um ciclo de dois estados, o usuário que força dark e depois quer voltar ao automático não sabe que precisa clicar de novo no mesmo botão. Com localStorage invisível, fica mágico demais. Um radio button com label explícito (Sistema, Claro, Escuro) é mais UI, sim, mas comunica a intenção sem deixar em aberto como desfaz. Às vezes menos código não vira melhor UX quando ninguém entende o modelo mental do toggle.

Ana Machado

A gente tá discutindo código, mas perdendo de vista que a maioria dos usuários não clica no toggle pra entender como funciona. Se o botão só mostra uma opção, ninguém descobre sozinho que é cíclico ou que existe um jeito de voltar pro automático. O localStorage invisível é elegante pra quem lê o artigo, mas pra usar é mágica demais. O radio button com três opções fica verboso no CSS, mas pelo menos comunica o modelo mental. Acho que a proposta do Lea é boa pro dev, mas não resolve o problema do usuário entender o que tá acontecendo.

Geraldo Godoy

A lógica do código fechado em dois estados é bem elegante, mas acho que o Lea meio que resolve um problema que não era o principal. O troço de três opções é feio mesmo, mas não por estar ali, é porque não comunica direito qual é o padrão e qual é o override. Um radio button com label explícito ('Sistema', 'Claro', 'Escuro') resolveria isso sem ficar mágico pro usuário. Ou seja, o problema real não é ter três estados, é como a gente apresenta eles.