# @property en CSS: animar degradados y propiedades personalizadas

[Canonical HTML page](https://gradiently.design/es/guide/css-property-animation)

Los degradados se niegan a hacer transiciones porque el navegador no puede fundir una imagen en otra. Dale un tipo a una propiedad personalizada y ese límite desaparece. Así funciona @property, con código para pegar.

## The short version

- @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.

**@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](https://gradiently.design/es/guide/css-animated-gradient). 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.

```css
@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%;
}
```

Tres propiedades registradas: un color, un ángulo y una posición de parada. Regístralas una vez, en el nivel superior de una hoja de estilos.

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.

| Sintaxis | Se anima con suavidad | Sirve para |
| --- | --- | --- |
| `<color>` | Sí | Colores de degradado, cambios de tema |
| `<angle>` | Sí | Ángulos lineales, rotación cónica |
| `<percentage>` | Sí | Posiciones de paradas de color, tamaños |
| `<length>` | Sí | Tamaños radiales, desplazamientos |
| `<number>` | Sí | Valores tipo opacidad, multiplicadores |
| `<integer>` | Sí, en pasos enteros | Contadores, efectos escalonados |
| `*` | No, salta | Todo lo que nunca vayas a animar |

Las sintaxis que importan para trabajar con degradados. También puedes aceptar varias, como `'<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.

```css
@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;
}
```

La transición nombra a la propiedad personalizada. Escribir transition: background no haría nada aquí.

- En reposo: --tint es violeta: `linear-gradient(120deg, #1e1b4b 0%, #7c3aed 100%)`
- A mitad de la transición: `linear-gradient(120deg, #1e1b4b 0%, #bb56b9 100%)`
- Hover: --tint es coral: `linear-gradient(120deg, #1e1b4b 0%, #fb7185 100%)`

Tres fotogramas del mismo botón. El color intermedio solo existe porque el navegador puede interpolar un color registrado.

Para más formas de tratar los botones, consulta [botones con degradado en CSS](https://gradiently.design/es/guide/css-gradient-button) y [efectos hover con degradado en CSS](https://gradiently.design/es/guide/css-hover-gradient).

## 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](https://gradiently.design/es/guide/css-conic-gradient) 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.

```css
@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; }
}
```

Repite el primer color al final para que desaparezca la costura donde 360deg se junta con 0deg.

El anillo cónico a 0deg: `conic-gradient(from 0deg, #22d3ee, #7c3aed, #f472b6, #22d3ee)`

El mismo degradado que usa el borde. A medida que crece --angle, este anillo gira, y la fina franja que ves alrededor de la tarjeta viaja con él. [Bordes con degradado en CSS](https://gradiently.design/es/guide/css-gradient-border) explica la versión estática.

## 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.

```css
@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%;
}
```

Dos paradas en la misma posición crean un borde nítido, y ese borde se mueve cuando cambia --stop.

## 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.

```js
if ('registerProperty' in CSS) {
  try {
    CSS.registerProperty({
      name: '--angle',
      syntax: '<angle>',
      inherits: false,
      initialValue: '0deg',
    })
  } catch {
    // Already registered, which is fine.
  }
}
```

La forma en JavaScript usa initialValue en camelCase. Todo lo demás coincide con la regla CSS.

## 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](https://caniuse.com/mdn-css_at-rules_property) 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.

> **Ojo con el repintado** Animar una propiedad usada en `background` obliga al navegador a repintar ese elemento en cada fotograma. Un borde o un botón pequeño cuestan poco; una cabecera a pantalla completa animada sin fin cuesta batería. [Rendimiento de los degradados CSS](https://gradiently.design/es/guide/css-gradient-performance) tiene las mediciones que conviene vigilar.

1. **Registra antes de usar** Pon cada regla `@property` en 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 de `background`.
4. **Respeta el movimiento reducido** Detén las animaciones en bucle con `prefers-reduced-motion: reduce`, como se explica en [prefers reduced motion](https://gradiently.design/es/guide/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](https://developer.mozilla.org/en-US/docs/Web/CSS/@property) recoge todos los descriptores.

## FAQ

### ¿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.
