Variáveis CSS (--*) sempre foram "burras": o navegador trata qualquer valor como texto solto, sem saber se é uma cor, um número ou um ângulo. A regra @property resolve isso registrando uma custom property com tipo definido, valor inicial e regra de herança — o que, entre outras coisas, destrava animações que antes eram impossíveis.
O problema: variáveis CSS não são animáveis
Tentar animar uma variável CSS comum não funciona como se espera. No exemplo abaixo, o navegador não sabe que --angulo é um ângulo, então ele simplesmente troca de um valor para o outro sem transição suave:
.fundo {
--angulo: 0deg;
background: conic-gradient(from var(--angulo), #12A8C3, #0C7A91);
transition: --angulo 0.4s ease;
}
.fundo:hover {
--angulo: 180deg;
}
Como o valor é tratado como texto genérico, o gradiente "pula" de uma posição para outra em vez de girar suavemente.
Como funciona o @property
Com @property, é possível registrar a variável informando um syntax (o tipo de dado), um initial-value (obrigatório, exceto quando o syntax é "*") e se ela deve herdar (inherits):
@property --angulo {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.fundo {
background: conic-gradient(from var(--angulo), #12A8C3, #0C7A91);
transition: --angulo 0.4s ease;
}
.fundo:hover {
--angulo: 180deg;
}
Agora o navegador sabe que --angulo é um <angle> e consegue interpolar valores intermediários durante a transição, girando o gradiente de forma suave.
Tipos de syntax mais comuns
@property --cor-destaque {
syntax: "<color>";
inherits: true;
initial-value: #12A8C3;
}
@property --escala {
syntax: "<number>";
inherits: false;
initial-value: 1;
}
@property --largura-barra {
syntax: "<percentage>";
inherits: false;
initial-value: 0%;
}
Os tipos mais usados são <color>, <number>, <percentage>, <length> e <angle>, mas também existem combinações com | (ex.: "<length> | <percentage>") e listas com +.
Exemplo prático: barra de progresso animada
@property --progresso {
syntax: "<percentage>";
inherits: false;
initial-value: 0%;
}
.barra {
width: 200px;
height: 8px;
background: #eee;
}
.barra::before {
content: "";
display: block;
height: 100%;
background: #12A8C3;
width: var(--progresso);
transition: --progresso 0.6s ease-out;
}
const barra = document.querySelector('.barra');
barra.style.setProperty('--progresso', '75%');
Como --progresso está registrada como <percentage>, a transição anima suavemente de 0% até 75%, em vez de pular direto para o valor final.
Validação de valores
Registrar o tipo também protege contra valores inválidos: se alguém tentar atribuir algo fora do syntax declarado, o navegador ignora a atribuição e usa o initial-value no lugar, em vez de aceitar qualquer texto.
Quando usar
- Animar gradientes, ângulos de rotação ou qualquer valor numérico guardado em variável CSS.
- Criar "design tokens" tipados, evitando que um valor de cor seja acidentalmente usado como número.
- Controlar explicitamente se uma variável herda (
inherits: true) ou fica isolada por componente (inherits: false). - Construir efeitos visuais complexos combinando
@propertycom@keyframes, já que também é possível animar via keyframes em vez de transition.
Cuidados
O registro via @property é global na página: se duas regras registrarem a mesma propriedade com syntax diferentes, vale o último registro válido processado, então é importante manter nomes de variáveis específicos por componente. Também existe a alternativa CSS.registerProperty() via JavaScript, mas ela não é reaproveitada entre page loads como o @property em CSS.
Compatibilidade
O @property é Baseline Widely Available: tem suporte em Chrome, Edge e Opera desde 2020, Safari desde a versão 16.4 e Firefox desde a versão 128, cobrindo praticamente todos os navegadores modernos em uso.
Conclusão
O @property transforma variáveis CSS de simples texto substituível em valores tipados que o navegador entende de verdade, destravando animações antes só possíveis com JavaScript ou truques de keyframes. É uma peça pequena, mas que muda bastante o que dá para fazer só com CSS.
0 Comentário
Deixe seu Comentário!
Dúvida, sugestão ou só um "valeu!" — tudo é bem-vindo por aqui.