CSS Houdini ha ido sumando APIs que llevan el control del estilo más allá de lo que permitían las hojas de estilo tradicionales, y @property es una de las más útiles del lote. Da a los desarrolladores una forma estándar de definir y registrar propiedades personalizadas de CSS con un tipo específico, herencia, valor por defecto y animaciones bastante más fluidas que las que se consiguen con variables CSS normales.
Vamos a ver cómo se usa @property, por qué merece la pena ahora que el soporte en navegadores ya es sólido, y un par de ejemplos prácticos que puedes adaptar directamente a tu proyecto.
Qué aporta @property frente a una custom property normal
Una custom property tradicional se declara así, sin más contexto para el navegador:
:root {
--color-primario: #ff0000;
}
@property añade información que el navegador antes no tenía: el tipo de valor (color, length, number…), un valor por defecto que actúa como fallback, si la propiedad es heredable o no por los elementos hijos, y la sintaxis que debe usar para interpretar el valor cuando cambie.
Ejemplo básico: animar una rotación
Supongamos que quieres que --giro sea una custom property de tipo angle para usarla en una animación de rotación:
@property --giro {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.carta {
transform: rotate(var(--giro));
transition: --giro 0.5s ease;
}
.carta:hover {
--giro: 45deg;
}
@property registra --giro como un ángulo con 0deg por defecto, y inherits: false evita que el valor se propague solo a los elementos hijos. El resultado son transiciones más fluidas y animaciones más eficientes, porque el navegador sabe exactamente cómo interpolar el valor en lugar de tratarlo como una cadena de texto sin estructura.
Por qué merece la pena usarlo ahora
El soporte de @property está ya consolidado en Safari, Firefox, Edge y Chrome, así que se puede llevar a producción sin depender de fallbacks o polyfills complicados. A medida que los componentes de UI se vuelven más complejos, tener un control preciso del tipo y la herencia de cada custom property da una base más sólida para animaciones avanzadas, componentes más aislados y resistentes a cambios, e integraciones con Web Animations API o con las Scroll-Driven Animations. Este tipo de control fino conecta directamente con lo que tratamos en motion design responsable: animaciones que no marean ni distraen, porque una animación bien tipada es también más fácil de moderar.
Ejemplo avanzado: animar un color
Si necesitas animar gradualmente el color de fondo de un elemento en hover, sin @property el navegador trata la custom property como texto plano y no sabe interpolarla. Registrándola como tipo color, el resultado cambia por completo:
@property --color-fondo {
syntax: "<color>";
inherits: false;
initial-value: #ffcccb;
}
.carta {
background: var(--color-fondo);
transition: --color-fondo 1s ease;
}
.carta:hover {
--color-fondo: #ff6666;
}
Con la sintaxis declarada, el navegador interpola entre los dos colores de forma correcta y la transición queda suave, en vez de saltar de golpe de un valor a otro.
Llevarlo más lejos: escalas y transformaciones
El mismo patrón sirve para registrar propiedades que controlen posición, tamaño o transformaciones:
@property --escala {
syntax: "<number>";
inherits: false;
initial-value: 1;
}
.carta {
transform: scale(var(--escala));
transition: --escala 0.5s ease;
}
.carta:hover {
--escala: 1.5;
}
Con esta información, el motor de renderizado ejecuta interpolaciones más eficientes en lugar de recalcular la transformación completa en cada frame, algo que pesa en el rendimiento cuando hay varias animaciones a la vez, un factor que también tratamos al hablar de cómo mejorar el CLS sin rediseñar tu web: cuanto mejor controlada está una animación, menos probable es que provoque saltos visuales.
Cuándo usarlo y cuándo no
Tiene sentido usar @property cuando necesitas que el navegador sepa interpolar o animar un valor concreto, cuando quieres añadir tipado y estructura a tus custom properties, o cuando buscas un estilo más declarativo y fácil de mantener en componentes complejos. No aporta gran cosa si solo declaras variables que no vas a animar ni manipular, y sigue sin ser una opción viable si necesitas dar soporte a navegadores muy antiguos, algo cada vez menos habitual y que conviene revisar junto a la estrategia general de velocidad de tu web antes de decidir qué nivel de soporte necesitas de verdad.
Preguntas frecuentes
¿Necesito un polyfill para usar @property?
En la mayoría de casos no, porque el soporte ya cubre Chrome, Edge, Firefox y Safari. Conviene comprobar la versión mínima que necesitas soportar antes de descartar el fallback por completo.
¿@property sustituye a las custom properties normales?
No, las complementa. Si solo necesitas una variable estática sin animar, una custom property normal sigue siendo suficiente y más simple.
¿Qué tipos de valor admite la sintaxis de @property?
Admite tipos como <color>, <length>, <number>, <angle>, <percentage> y combinaciones de estos, entre otros definidos en la especificación de CSS Typed OM.
¿Puedo usar @property también con JavaScript?
Sí, existe también CSS.registerProperty(), la versión en JavaScript de la misma funcionalidad, útil cuando necesitas registrar propiedades de forma dinámica.
¿Mejora realmente el rendimiento de las animaciones?
Sí, porque el navegador deja de tratar el valor como texto plano y puede interpolarlo de forma nativa, lo que reduce el trabajo de cálculo en cada frame de la animación.


