⚡ Curso de CSS • Web-ZoneWare

CSS Variables e Dark Mode Dinâmico no CSS | Web Academy

Lição 45 de 50

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.

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():

CSS3 13 linhas
/* 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:

CSS3 9 linhas
/* 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:

CSS3 16 linhas
: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:

CSS3 10 linhas
/* 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:

CSS3 37 linhas
/* 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:

JavaScript 5 linhas
// 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:

HTML5 106 linhas
<!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:

⚡ Abrir no Playground IDE →

7. Resumo e Próximos Passos

  • CSS Variables (Custom Properties) são declaradas com --nome e consumidas com var(--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 :root e 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)!

Rolar para cima