Menu

Animaciones en CSS: @keyframes, propiedades y ejemplos

Las animaciones CSS llevan un elemento por los pasos que defines en @keyframes, solas y tantas veces como quieras. Aprende la sintaxis de @keyframes, las ocho propiedades de animation, fill-mode y direction, indicadores de carga, cómo pausarlas y cómo respetar el movimiento reducido.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Una animación CSS en un ejemplo

Una animación tiene dos partes: @keyframes, que describe los pasos, y la propiedad animation, que los aplica a un elemento con una duración. Esta tarjeta entra deslizándose y apareciendo cuando carga la página:

Edita el código (o cambia la duración a 2s) y la vista previa se recarga, así que puedes ver entrar la tarjeta otra vez. El bloque @media (prefers-reduced-motion: reduce) reemplaza los keyframes por un simple desvanecido solo para los lectores cuyo sistema está configurado para reducir el movimiento.

Sintaxis de @keyframes

@keyframes pulse {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.08); }
  100% { transform: scale(1); }
}
  • from es lo mismo que 0% y to es lo mismo que 100%.
  • Agrega tantos pasos en porcentaje como necesites. Los pasos con los mismos estilos pueden compartir línea: 0%, 100% { ... }.
  • Una propiedad que falta en el primer o el último keyframe se anima desde o hasta el valor propio del elemento.
  • El nombre (pulse) es lo que le pasas a animation-name. Distingue mayúsculas y minúsculas y no puede ser una palabra clave como none.

Las propiedades de animation

PropiedadQué definePor defecto
animation-namequé @keyframes ejecutarnone
animation-durationla duración de un ciclo0s
animation-timing-functionla curva de velocidad entre keyframesease
animation-delayespera antes del primer ciclo (negativo empieza a mitad de camino)0s
animation-iteration-countcantidad de ciclos, o infinite1
animation-directionnormal, reverse, alternate, alternate-reversenormal
animation-fill-modeestilos antes y después: none, forwards, backwards, bothnone
animation-play-staterunning o pausedrunning

La abreviatura los acepta casi en cualquier orden. La única regla es que el primer valor de tiempo es la duración y el segundo el retraso:

.loader {
  animation: pulse 1.2s ease-in-out 0.2s infinite alternate both;
  /*         name  duration timing  delay count   direction fill */
}

direction y fill-mode, en vivo

Elige una dirección, un fill mode y una cantidad, y presiona Play. La caja se mueve 200px hasta el final de la pista. El indicador dice dónde quedó cuando terminó la animación:

Qué observar:

  • fill-mode: none (el valor por defecto): después del último fotograma la caja vuelve de golpe a x = 0 y se pone ámbar otra vez.
  • forwards: se queda en el último keyframe. Con normal eso es x = 200 y verde; con reverse termina en x = 0 y azul, porque el último keyframe reproducido fue from.
  • alternate con una cantidad de 2 va y vuelve, así que incluso con forwards termina en x = 0.

Bucles infinitos: un indicador de carga

infinite repite para siempre, y un animation-delay en cada hijo los desfasa para que se muevan por turnos. Mantén los bucles tranquilos: lentos, pequeños, sin destellos.

role="status" con un aria-label les dice a los usuarios de lectores de pantalla que algo está cargando, algo que los puntos solos no dicen. Para un círculo que gira, consulta la página de rotar.

Pausar y controlar animaciones

animation-play-state: paused congela una animación donde está, y running la continúa desde ahí. Pasa el mouse por la barra de abajo para pausarla:

Desde JavaScript, element.getAnimations() devuelve las animaciones CSS en curso, cada una con pause(), play(), cancel() y un currentTime que puedes leer o cambiar. El evento animationend se dispara cuando termina una animación no infinita, y animationiteration al final de cada ciclo.

Respeta el movimiento reducido y nunca uses destellos

Dos reglas de accesibilidad se aplican a toda animación:

  1. Movimiento reducido. Las personas pueden pedirle a su sistema menos movimiento porque el movimiento las hace sentir mal. El patrón más seguro es agregar movimiento solo cuando no han pedido menos:
@media (prefers-reduced-motion: no-preference) {
  .hero-title { animation: slide-in 0.8s ease-out both; }
}
  1. Sin destellos. El contenido que destella más de tres veces por segundo puede provocar convulsiones. Evita por completo los parpadeos rápidos y de alto contraste.

Mantén las animaciones fluidas

Anima transform y opacity cuando puedas. El navegador puede aplicarlas sin volver a acomodar la página, así que se mantienen fluidas incluso en teléfonos lentos. Animar width, height, top, left o margin recalcula el layout en cada fotograma. Para mover un elemento, usa translate() de la página de transform.

Errores comunes

  • Sin duración. animation: fade; no hace nada, porque la duración por defecto es 0s.
  • Un nombre que no coincide. animation-name debe coincidir exactamente con el nombre de @keyframes, mayúsculas incluidas.
  • Volver de golpe al final. Agrega forwards (o both) para conservar el último keyframe.
  • Un parpadeo antes de que empiece una animación con retraso. Durante animation-delay el elemento muestra sus estilos normales. backwards (o both) aplica el primer keyframe durante el retraso.
  • Reiniciar una animación poniendo el mismo valor. Volver a poner el mismo animation no hace nada. Quítalo, fuerza un reflow (el.offsetWidth) y vuelve a ponerlo, como hace el botón Play de arriba.
  • Animar display. Cambia de golpe. Anima opacity y transform.

Preguntas frecuentes

¿Cómo se hace una animación en CSS?

Define los pasos con @keyframes name { from { ... } to { ... } } y aplícala a un elemento con la propiedad animation y una duración: animation: name 1s ease-out;. La duración es obligatoria, porque su valor por defecto es 0s.

¿Qué hace animation-fill-mode: forwards?

Mantiene los estilos del último keyframe cuando termina la animación. Sin él, el elemento vuelve de golpe a sus estilos normales. backwards aplica el primer keyframe durante el retraso, y both hace las dos cosas.

¿Cómo hago que una animación CSS se repita para siempre?

Define animation-iteration-count: infinite, o agrega infinite a la abreviatura: animation: spin 1s linear infinite;. Agrega alternate para reproducirla hacia adelante y luego hacia atrás en cada ciclo.

¿Qué diferencia hay entre animation y transition en CSS?

Una transición anima una propiedad entre dos valores cuando cambia, normalmente en hover o con un cambio de clase. Una animación se ejecuta sola en cuanto se aplica, puede tener cualquier cantidad de keyframes y puede repetirse, invertirse y pausarse.

¿Cómo pauso una animación CSS?

Define animation-play-state: paused en el elemento, por ejemplo en :hover o con una clase que agrega JavaScript. Volver a ponerlo en running la continúa desde donde se detuvo.

¿Cómo desactivo las animaciones para quienes prefieren menos movimiento?

Envuelve la animación en @media (prefers-reduced-motion: no-preference) { ... }, o quítala dentro de @media (prefers-reduced-motion: reduce) { ... }. La consulta sigue la opción de reducir movimiento del sistema operativo del usuario.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR