CSS Variables e Dark Mode Dinâmico no CSS | Web Academy
Durante muitos anos, o gerenciamento de cores e medidas no CSS foi caótico. Se a sua empresa decidisse alterar o azul corporativo da marca, você era forçado a fazer um “localizar e substituir” em milhares de linhas de código, com o risco constante de esquecer elementos. As CSS Custom Properties, universalmente chamadas de CSS Variables, representaram o maior salto de engenharia de software da história do CSS. Ao contrário das variáveis antigas de pré-processadores como o Sass, as variáveis CSS vivem no DOM em tempo de execução, herdam pela cascata, reagem a media queries e podem ser manipuladas instantaneamente pelo JavaScript para alternar entre Modo Claro e Modo Escuro com zero recarregamento de página.
📑 Índice do Conteúdo
1. A Sintaxe: Declarando e Consumindo Variáveis
A declaração de uma variável CSS sempre inicia com dois traços (--), e o seu consumo é feito através da função var():
/* 1. DECLARAÇÃO GLOBAL NO :root */
:root {
--cor-primaria: #38bdf8;
--espacamento-padrao: 16px;
--raio-borda: 10px;
}
/* 2. CONSUMO EM QUALQUER SELETOR */
.cartao {
border: 1px solid var(--cor-primaria);
padding: var(--espacamento-padrao);
border-radius: var(--raio-borda);
}
Valores de Reserva (Fallbacks)
A função var() aceita um segundo parâmetro opcional como valor de segurança (fallback). Se a variável não estiver definida no escopo, o navegador adota o fallback automaticamente:
/* Se --cor-destaque não existir, usa #2563eb */
.btn {
background-color: var(--cor-destaque, #2563eb);
}
/* Fallback encadeado em cascata */
.titulo {
color: var(--cor-customizada, var(--cor-primaria, #0f172a));
}
2. Escopo Global vs. Escopo Local (A Cascata Viva)
O maior diferencial das CSS Variables sobre o Sass é que elas respeitam o escopo da árvore do DOM:
1. Escopo Global (:root)
O pseudo-elemento :root representa a raiz do documento (o elemento <html>), mas possui uma especificidade maior. Qualquer variável declarada no :root é herdada por absolutamente todos os elementos da página.
2. Escopo Local (Component-Level Overriding)
Você pode redefinir o valor de uma variável dentro de um contêiner específico. Apenas aquele contêiner e seus filhos passarão a enxergar o novo valor:
:root {
--btn-bg: #2563eb; /* Azul padrão global */
}
/* Um banner de perigo reescreve a variável localmente */
.banner-alerta {
--btn-bg: #ef4444; /* Vermelho apenas dentro do banner! */
background: #450a0a;
padding: 20px;
}
/* O botão consome --btn-bg: se estiver no site é azul, se estiver no banner é vermelho! */
.btn-acao {
background-color: var(--btn-bg);
color: #fff;
}
3. A Regra de Ouro dos Tokens Semânticos
Anti-padrão Fatal: Nunca nomeie suas variáveis com nomes de cores físicas (como --azul, --verde ou --cinza-escuro). Quando você criar o Modo Escuro, o seu “azul” ou “branco” precisará virar cinza escuro ou preto, tornando seu código confuso e ilegível!
Use sempre Design Tokens Semânticos baseados na função visual do elemento:
/* SISTEMA PROFISSIONAL DE DESIGN TOKENS */
:root {
--bg-pagina: #ffffff;
--bg-superficie: #f8fafc;
--bg-card: #ffffff;
--texto-primario: #0f172a;
--texto-secundario: #64748b;
--borda-suave: #e2e8f0;
--cor-marca: #2563eb;
}
4. Arquitetura Definitiva de Dark Mode
Para criar um sistema de tema escuro de classe mundial, combinamos a detecção automática do sistema operacional com a capacidade de o usuário forçar o tema manualmente através de um atributo data-theme:
/* 1. TEMA CLARO PADRÃO */
:root {
--bg-pagina: #f8fafc;
--bg-card: #ffffff;
--texto-corpo: #0f172a;
--borda: #cbd5e1;
--destaque: #2563eb;
}
/* 2. MODO ESCURO AUTOMÁTICO (PREFERÊNCIA DO SISTEMA OPERACIONAL) */
@media (prefers-color-scheme: dark) {
:root {
--bg-pagina: #0b0f19;
--bg-card: #1e293b;
--texto-corpo: #f8fafc;
--borda: #334155;
--destaque: #38bdf8;
}
}
/* 3. MODO ESCURO FORÇADO VIA JAVASCRIPT (DATA-THEME="DARK") */
[data-theme="dark"] {
--bg-pagina: #0b0f19;
--bg-card: #1e293b;
--texto-corpo: #f8fafc;
--borda: #334155;
--destaque: #38bdf8;
}
/* 4. MODO CLARO FORÇADO VIA JAVASCRIPT (DATA-THEME="LIGHT") */
[data-theme="light"] {
--bg-pagina: #f8fafc;
--bg-card: #ffffff;
--texto-corpo: #0f172a;
--borda: #cbd5e1;
--destaque: #2563eb;
}
5. Reatividade em Tempo Real com JavaScript
Como as CSS Variables vivem no DOM computado, você pode manipulá-las diretamente pelo JavaScript sem precisar recalcular regras de classe:
// Altera uma variável global instantaneamente:
document.documentElement.style.setProperty('--destaque', '#10b981');
// Lê o valor computado de uma variável:
const corAtual = getComputedStyle(document.documentElement).getPropertyValue('--destaque');
6. Laboratório Prático: Switcher de Dark Mode Completo
No código interativo abaixo, construímos um componente de dashboard que consome tokens semânticos e alterna dinamicamente entre Tema Claro e Tema Escuro ao clique de um botão:
<!DOCTYPE html>
<html lang="pt-BR" data-theme="dark">
<head>
<meta charset="UTF-8">
<title>Laboratório de CSS Variables e Dark Mode</title>
<style>
/* TOKENS SEMÂNTICOS NO ESCOPO RAIZ */
:root, [data-theme="dark"] {
--bg: #0b0f19;
--card-bg: #1e293b;
--texto: #f8fafc;
--texto-mutado: #94a3b8;
--borda: #334155;
--primaria: #38bdf8;
--btn-texto: #0b0f19;
}
[data-theme="light"] {
--bg: #f1f5f9;
--card-bg: #ffffff;
--texto: #0f172a;
--texto-mutado: #64748b;
--borda: #cbd5e1;
--primaria: #2563eb;
--btn-texto: #ffffff;
}
body {
background-color: var(--bg);
color: var(--texto);
font-family: 'Inter', system-ui, sans-serif;
padding: 40px;
margin: 0;
transition: background-color 0.3s ease, color 0.3s ease;
}
.painel-container {
max-width: 480px;
background-color: var(--card-bg);
border: 1px solid var(--borda);
border-radius: 14px;
padding: 24px;
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
transition: background-color 0.3s ease, border-color 0.3s ease;
}
.cabecalho-card {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
h3 { margin: 0; color: var(--primaria); font-size: 1.2rem; }
p {
color: var(--texto-mutado);
font-size: 0.9rem;
line-height: 1.6;
margin: 0 0 20px 0;
}
/* Botão que troca o tema via JavaScript */
.btn-toggle-tema {
background-color: var(--primaria);
color: var(--btn-texto);
border: none;
padding: 10px 16px;
border-radius: 8px;
font-weight: 700;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 8px;
transition: transform 0.2s ease;
}
.btn-toggle-tema:active {
transform: scale(0.96);
}
</style>
</head>
<body>
<div class="painel-container">
<div class="cabecalho-card">
<h3>⚡ Web-ZoneWare Theme</h3>
<button class="btn-toggle-tema" onclick="alternarTema()">
🌓 Alternar Tema
</button>
</div>
<p>
Este cartão consome exclusivamente variáveis CSS semânticas (<code>--bg</code>, <code>--card-bg</code>, <code>--primaria</code>). Clique no botão acima para alternar entre Dark e Light Mode em tempo real!
</p>
</div>
<script>
function alternarTema() {
const html = document.documentElement;
const temaAtual = html.getAttribute('data-theme');
const novoTema = (temaAtual === 'dark') ? 'light' : 'dark';
html.setAttribute('data-theme', novoTema);
}
</script>
</body>
</html>
Abra este laboratório no Playground IDE e teste clicar no botão de alternância para ver todas as cores do cartão e do fundo se transformarem suavemente sem recarregar a página:
7. Resumo e Próximos Passos
- CSS Variables (Custom Properties) são declaradas com
--nomee consumidas comvar(--nome, fallback). - Vivem na árvore do DOM em tempo de execução, respeitam o escopo da cascata e herdam valores de pais para filhos.
- Declare tokens globais no
:roote use tokens semânticos funcionais (como--bg-card) em vez de nomes físicos de cores. - A fusão de
@media (prefers-color-scheme)com[data-theme]cria sistemas de Dark Mode elegantes e controláveis pelo usuário. - O JavaScript pode ler e atualizar variáveis CSS dinamicamente através de
setProperty().
Próximo Passo: Agora que você domina as variáveis e o Dark Mode, como criar aquela estética translúcida futurista de vidro fosco (Glassmorphism) com desfoque de fundo e filtros visuais? Na Lição 46, mergulharemos em Filtros & Glassmorphism no CSS (filter e backdrop-filter)!