Variáveis CSS (Custom Properties) e Theming
2 min de leitura
Variáveis CSS (formalmente, custom properties) são a base de
qualquer design system moderno. Em vez de espalhar #1a73e8 por
todo o CSS, você define uma vez: --cor-primaria: #1a73e8; e usa
onde precisar. Mudou a cor? Um lugar só.
Definindo e usando
:root {
--cor-primaria: #1a73e8;
--cor-secundaria: #6f42c1;
--espacamento-padrao: 16px;
--raio-borda: 8px;
--fonte-principal: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.botao {
background: var(--cor-primaria);
padding: var(--espacamento-padrao);
border-radius: var(--raio-borda);
font-family: var(--fonte-principal);
}
A sintaxe é:
- Declaração:
--nome-da-variavel: valor;(sempre começa com--) - Uso:
var(--nome-da-variavel)
Onde declarar
A "variável" é herdada em cascata como qualquer propriedade CSS. Onde você declara, ela vale para aquele elemento e seus filhos.
:root { --cor: blue; } /* vale pra página inteira */
.dark { --cor: white; } /* sobrescreve em .dark */
O :root é o seletor do elemento <html>, então declarar em :root
torna a variável global. É o padrão para design system.
Valor de fallback
.botao {
background: var(--cor-primaria, #1a73e8);
/* └─ valor padrão se a variável não existir */
}
Se --cor-primaria não foi declarada em nenhum ancestral, o
navegador usa #1a73e8. Defensivo, mas não exagere - se você controla
o projeto, prefira declarar sempre.
Variáveis dinâmicas (a parte poderosa)
Variáveis CSS mudam em tempo real, sem pré-processador. Você pode mudar via JavaScript, mas também com CSS puro:
.cartao {
--angulo: 0deg;
background: linear-gradient(var(--angulo), #1a73e8, #6f42c1);
}
.cartao:hover { --angulo: 90deg; }
Mude o valor da variável e tudo que usa ela recalcula. Você pode construir um slider de cor sem JavaScript:
input[type="range"] {
--valor: 50;
background: hsl(calc(var(--valor) * 3.6), 70%, 50%);
}
OK, esse é meio hack - mas a ideia é: variáveis são computadas em cascata, em tempo real, dentro de qualquer propriedade que aceite cálculo.
Theming (light/dark mode)
Esse é o caso de uso que mais justifica aprender variáveis:
:root {
--bg: white;
--texto: #1a1a1a;
--borda: #e0e0e0;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--texto: #f0f0f0;
--borda: #2a2a2a;
}
}
body {
background: var(--bg);
color: var(--texto);
}
.card {
border: 1px solid var(--borda);
}
Um único bloco de CSS troca o tema. Sem .dark em cada componente,
sem overrides espalhados.
Theming com toggle manual
:root { --bg: white; --texto: #1a1a1a; }
:root.tema-escuro { --bg: #1a1a1a; --texto: #f0f0f0; }
body { background: var(--bg); color: var(--texto); }
<button onclick="document.documentElement.classList.toggle('tema-escuro')">
Trocar tema
</button>
A classe no <html> muda a variável, que muda a página inteira.
@property: a evolução das variáveis
@property --angulo {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
Antes do @property, mudar uma variável não animava - a troca
era instantânea, sem interpolação. Com @property, você registra a
variável, declara o tipo (<angle>, <color>, <length>, etc.) e o
navegador pode interpolar entre valores. Suporte recente mas
poderoso.
@property --progresso {
syntax: "<percentage>";
initial-value: 0%;
inherits: false;
}
.barra {
--progresso: 0%;
width: var(--progresso);
transition: --progresso 1s ease-out;
}
.barra.carregou { --progresso: 100%; }
A barra anima de 0% a 100% suavemente. Sem JavaScript, sem gambiarra.
- Declare com
--nome: valor;no:rootpara global. - Use com
var(--nome)em qualquer propriedade. - Herança automática: filhos veem a variável do pai.
- Fallback:
var(--nome, valor). @propertyregistra a variável com tipo, permitindo interpolação.
Dica: a regra de ouro é nunca mais hardcode uma cor, espaçamento ou fonte no CSS. Tudo via variável. Em 6 meses, quando o design pedir para mudar a cor primária, você muda uma linha em vez de 80.
No próximo nó, vamos ver @keyframes e a propriedade animation
- a diferença entre "transição entre dois estados" e "animação com múltiplos passos e repetição".