O que são variáveis CSS?
As variáveis CSS, chamadas corretamente de custom properties, são valores que você define uma vez e referencia em qualquer lugar. Elas se parecem com propriedades comuns, mas começam com --, e você as lê utilizando a função var().
/* tokens.css */
:root {
--color-brand: #2563eb;
--radius: 0.5rem;
--space-4: 1rem;
}
.button {
background: var(--color-brand);
border-radius: var(--radius);
padding: var(--space-4) calc(var(--space-4) * 1.5);
}
A principal diferença em relação a uma variável de pré-processador é que as custom properties fazem parte da cascata do navegador. Elas são herdadas, podem ter escopo definido e podem mudar em tempo de execução. Isso as torna a camada natural para a implementação de temas e design tokens.
Declarando e utilizando
Declare uma propriedade customizada com um nome que comece com dois traços e qualquer valor válido.
/* declare.css */
:root {
--gap: 1.5rem;
--shadow: 0 1px 2px rgb(0 0 0 / 0.08);
--font-sans: "Inter", system-ui, sans-serif;
}
.card {
gap: var(--gap);
box-shadow: var(--shadow);
font-family: var(--font-sans);
}
Os valores podem ser quase qualquer coisa: cores, comprimentos, sombras, pilhas de fontes, gradientes ou até mesmo fragmentos de um valor. Como eles são substituídos antes de a propriedade ser analisada, podem ser combinados com calc().
A cascata e a herança
As propriedades customizadas seguem as regras normais do CSS. Uma declaração em um elemento é herdada por seus descendentes, e a declaração mais próxima prevalece.
/* scope.css */
:root {
--accent: #2563eb;
}
.sidebar {
--accent: #f97316;
}
.sidebar a {
color: var(--accent); /* orange inside the sidebar */
}
É isso que torna o escopo tão poderoso: você pode alterar o tema de um componente ou de uma seção sem mexer nos tokens globais. É também por isso que definir tokens no :root os torna disponíveis em qualquer lugar.
Fallbacks
var() aceita um fallback como segundo argumento, utilizado quando a propriedade está ausente ou é inválida.
/* fallback.css */
.button {
color: var(--button-color, #ffffff);
background: var(--button-bg, var(--color-brand, #2563eb));
}
Fallbacks são úteis para componentes reutilizáveis que devem funcionar mesmo quando os tokens não estão definidos, e eles podem ser aninhados. No entanto, use-os com moderação; se um token deve sempre existir, defina-o claramente em vez de esconder o problema.
Tematização
A tematização é o caso de uso principal. Altere um conjunto de variáveis e toda uma subárvore é atualizada.
/* theme.css */
:root {
--bg: #ffffff;
--surface: #f8fafc;
--text: #0f172a;
--border: #e2e8f0;
}
[data-theme="dark"] {
--bg: #0b0d0c;
--surface: #14161a;
--text: #e5e7eb;
--border: #26292e;
}
body {
background: var(--bg);
color: var(--text);
}
.card {
background: var(--surface);
border: 1px solid var(--border);
}
Alterne um atributo data-theme no elemento raiz e a página inteira muda de tema instantaneamente, sem regras duplicadas. Você também pode restringir um tema a um componente, permitindo que um card escuro fique em uma página clara.
Valores dinâmicos com JavaScript
Como as propriedades customizadas residem no DOM, você pode lê-las e escrevê-las via JavaScript.
// progress.js
const bar = document.querySelector(".progress");
function setProgress(percent) {
bar.style.setProperty("--progress", `${percent}%`);
}
setProgress(72);
/* progress.css */
.progress__fill {
width: var(--progress, 0%);
}
É assim que barras de progresso, interações de drag, efeitos de cursor e alternadores de tema são comumente construídos. O valor permanece no CSS e o JavaScript apenas atualiza um número.
Propriedades tipadas com @property
Por padrão, as custom properties são strings sem tipo, por isso o navegador não consegue interpolá-las. A at-rule @property registra um tipo, um valor inicial e um comportamento de herança.
/* property.css */
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.spinner {
background: conic-gradient(from var(--angle), #2563eb, transparent);
animation: rotate 1s linear infinite;
}
@keyframes rotate {
to { --angle: 360deg; }
}
Com um tipo registrado, a propriedade torna-se animável e o navegador valida o valor, o que evita toda uma classe de bugs.
Melhores práticas
- Defina tokens globais em
:roote utilize-os em todo o projeto. - Nomeie os tokens pelo propósito (
--color-text) e não pela aparência (--gray-900). - Sobrescreva variáveis para temas e variantes de componentes em vez de duplicar regras.
- Forneça fallbacks para componentes reutilizáveis que possam ser executados sem tokens.
- Atualize variáveis via JavaScript em vez de escrever estilos inline em todos os lugares.
- Registre propriedades animáveis com
@property. - Mantenha o conjunto de tokens pequeno e consistente.
Erros comuns
- Esperar que as custom properties se comportem como variáveis Sass em tempo de build.
- Usar nomes vagos que tornam o conjunto de tokens difícil de manter.
- Definir cada valor como uma variável e prejudicar a legibilidade.
- Esquecer que os valores não possuem tipagem, a menos que sejam registrados com
@property. - Sobrescrever tokens globalmente quando apenas uma subárvore deveria ser alterada.
- Armazenar segredos ou dados de usuário em variáveis CSS, que ficam visíveis no DOM.
Próximos passos
As custom properties são o tecido conectivo de uma stylesheet sustentável. Aplique-as ao layout com Design Responsivo, anime as propriedades tipadas com Animações e Transições e entenda a cascata por trás delas no guia de CSS. Para variáveis de build-time que as complementam, veja Sass.