La versión corta
- @property en CSS registra una propiedad personalizada con una sintaxis, una regla de herencia y un valor inicial, lo que le dice al navegador qué tipo de valor contiene.
- Los navegadores no pueden hacer una transición directa de un degradado, porque background-image no es interpolable, pero sí de una propiedad personalizada con tipo usada dentro del degradado.
- Las propiedades con tipo como <color>, <angle>, <percentage> y <length> se animan con suavidad; una propiedad con la sintaxis universal * solo salta de un valor a otro.
- La regla @property funciona en las versiones actuales de Chrome, Edge, Safari y Firefox, y los navegadores que la ignoran simplemente muestran el degradado sin movimiento.
- Animar una propiedad personalizada dentro de un fondo repinta el elemento en cada fotograma, así que mantén moderada la zona animada y respeta prefers-reduced-motion.
En esta página
@property en CSS registra una propiedad personalizada con un tipo, para que el navegador sepa que --angle contiene un ángulo o que --tint contiene un color. Una vez que conoce el tipo, puede interpolar entre dos valores, lo que significa que puedes hacer transiciones y animaciones de cosas que CSS normalmente se niega a mover: colores de degradado, ángulos de degradado y la posición de una parada de color. Sin registro, una propiedad personalizada es solo una cadena de texto, y una cadena solo puede saltar de un valor al siguiente.
Por qué los degradados no hacen transiciones por sí solos
Prueba transition: background 0.4s en un botón cuyo estado hover cambia un linear-gradient() por otro y nada se suaviza: el degradado nuevo aparece de golpe. Los degradados son imágenes, y la especificación trata background-image como no interpolable, así que el navegador no tiene forma de fundir una imagen en otra distinta.
El rodeo habitual es sobredimensionar el fondo y deslizar background-position, que es como se construyen la mayoría de los degradados animados en CSS. Funciona, pero solo mueve un degradado fijo de un lado a otro. No puedes cambiar un color, girar un ángulo ni desplazar una parada. Las propiedades registradas lo cambian, porque lo que se anima ya no es la imagen sino un número o un color con tipo dentro de ella. El navegador recalcula el degradado en cada fotograma a partir del valor actual.
--tint sin registrar
- Se guarda como una cadena de tokens
- Las transiciones saltan a mitad de camino
- Se hereda por defecto
- Un valor no válido rompe la declaración al calcularse
Registrada con @property
- Se interpreta como un color real
- Las transiciones interpolan con suavidad
- La herencia la decides tú
- Un valor no válido vuelve al valor inicial
La sintaxis de @property
Una regla @property tiene tres descriptores. syntax dice qué tipo de valor se permite, inherits dice si los hijos reciben el valor e initial-value se usa cuando nada más lo define. Los tres son obligatorios, salvo initial-value, que se puede omitir cuando la sintaxis es *. Si falta alguna parte obligatoria o está mal, el navegador ignora toda la regla, sin avisar.
@property --tint {
syntax: '<color>';
inherits: false;
initial-value: #7c3aed;
}
@property --angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
@property --stop {
syntax: '<percentage>';
inherits: false;
initial-value: 40%;
}El valor inicial debe ser computacionalmente independiente, lo que en la práctica significa unidades absolutas: 0deg, 40%, 12px y los colores hex valen, mientras que 2em o var(--x) no. Definir inherits: false suele ser lo que quieres para animar, y le ahorra al navegador propagar el valor por el árbol.
<color>Se anima con suavidad
Sirve para
<angle>Se anima con suavidad
Sirve para
<percentage>Se anima con suavidad
Sirve para
<length>Se anima con suavidad
Sirve para
<number>Se anima con suavidad
Sirve para
<integer>Se anima con suavidad
Sirve para
*No, saltaSirve para
'<length> | <percentage>', o una lista con +.Animar un color de degradado en hover
Este es el ejemplo útil más pequeño. El botón usa --tint como segundo color, y el estado hover solo cambia --tint. Como la propiedad está registrada como color, la transición se suaviza entre el violeta y el coral en lugar de saltar.
@property --tint {
syntax: '<color>';
inherits: false;
initial-value: #7c3aed;
}
.button {
background: linear-gradient(120deg, #1e1b4b 0%, var(--tint) 100%);
transition: --tint 400ms ease;
}
.button:hover {
--tint: #fb7185;
}Para más formas de tratar los botones, consulta botones con degradado en CSS y efectos hover con degradado en CSS.
Girar el borde de un degradado cónico
Un uso favorito de @property es un borde que parece recorrer una tarjeta. Un degradado cónico parte de un ángulo, así que registrar ese ángulo y animarlo de 0deg a 360deg hace girar los colores. Dos fondos hacen el trabajo: el color de la tarjeta recortado a la caja de relleno y el degradado cónico recortado a la caja del borde.
@property --angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
.card {
border: 2px solid transparent;
border-radius: 16px;
background:
linear-gradient(#0f0b1e, #0f0b1e) padding-box,
conic-gradient(from var(--angle), #22d3ee, #7c3aed, #f472b6, #22d3ee) border-box;
animation: spin 6s linear infinite;
}
@keyframes spin {
to { --angle: 360deg; }
}
@media (prefers-reduced-motion: reduce) {
.card { animation: none; }
}conic-gradient(from 0deg, #22d3ee, #7c3aed, #f472b6, #22d3ee)Mover una parada de color
Un porcentaje registrado permite que una parada se deslice. Úsalo para una barra de progreso, un realce que recorre un titular o un horizonte que sube con el scroll. Aquí --stop mueve el punto en el que el degradado pasa de tinta a verde azulado.
@property --stop {
syntax: '<percentage>';
inherits: false;
initial-value: 20%;
}
.meter {
background: linear-gradient(90deg, #0d9488 0%, #0d9488 var(--stop), #0f172a var(--stop));
transition: --stop 600ms ease-out;
}
.meter[data-done] {
--stop: 100%;
}Registrar desde JavaScript
CSS.registerProperty() hace lo mismo desde un script. Es práctico cuando un sistema de diseño registra sus propiedades en tiempo de ejecución, o cuando un valor solo se conoce después de cargar. Registrar el mismo nombre dos veces lanza un error, así que protégelo.
if ('registerProperty' in CSS) {
try {
CSS.registerProperty({
name: '--angle',
syntax: '<angle>',
inherits: false,
initialValue: '0deg',
})
} catch {
// Already registered, which is fine.
}
}Soporte en navegadores, alternativas y rendimiento
@property funciona en las versiones actuales de Chrome, Edge, Safari y Firefox; Firefox fue el último en añadirlo, en la versión 128. Consulta caniuse si das soporte a dispositivos más antiguos. Un navegador que no entiende la regla trata --angle como una propiedad personalizada normal, así que tu degradado se sigue dibujando con su valor inicial y simplemente no se mueve. Es una alternativa correcta, siempre que el fotograma estático se vea terminado.
- 1
Registra antes de usar
Pon cada regla
@propertyen el nivel superior, fuera de las media queries, para que se aplique en todas partes. - 2
Usa sintaxis con tipo
Elige
<color>,<angle>o<percentage>. Evita*para todo lo que pienses animar. - 3
Anima la propiedad
Escribe
transition: --tint 400ms, nombrando la propiedad personalizada en lugar debackground. - 4
Respeta el movimiento reducido
Detén las animaciones en bucle con
prefers-reduced-motion: reduce, como se explica en prefers reduced motion. - 5
Revisa el fotograma quieto
Desactiva la animación y asegúrate de que el degradado en reposo sigue viéndose intencionado.
Si el movimiento que buscas vive en posts de redes o en vídeo y no en una página web, un Mark de Gradiently ya lleva su propia luz y su movimiento lento, y Pro lo exporta en MP4, WebM o GIF donde el navegador admite la grabación, sin escribir keyframes. Para todo lo que está en la web, @property es la herramienta más limpia que tienes. La referencia de MDN recoge todos los descriptores.
Preguntas frecuentes
¿Qué hace @property en CSS?
Registra una propiedad personalizada con un tipo, una regla de herencia y un valor inicial. Conocer el tipo permite al navegador validar el valor e interpolarlo en transiciones y animaciones.
¿Se puede animar un degradado CSS?
No directamente, porque background-image no es interpolable. Registra los colores, el ángulo o las posiciones de las paradas con @property, úsalos dentro del degradado y anima esas propiedades.
¿Por qué no funciona mi animación con @property?
Normalmente falta un descriptor, el valor inicial usa una unidad relativa, la sintaxis es * o la transición nombra background en lugar de la propiedad personalizada. Cualquier descriptor no válido hace que el navegador ignore toda la regla.
¿Firefox admite @property?
Sí. Firefox añadió @property en la versión 128, así que ya funciona en todos los navegadores principales actuales.
¿inherits debe ser true o false?
Usa false para la mayoría de los valores animados. Mantiene el valor en el elemento donde lo defines y evita trabajo extra al navegador.
Escrito por Gradiently
El equipo detrás de Gradiently, una herramienta de diseño creada en torno a los Marks: degradados vivos que hacen que todo lo que diseñas parezca tuyo.
Ver nuestro perfil