Curso de CSS / animaciones con fotogramas clave, fill-mode y pausa

Las animaciones CSS con keyframes describen los valores de las propiedades a lo largo de la línea de tiempo de una animación y pueden ejecutarse sin un disparador de hover o focus. La duración, el retraso, el número de iteraciones, el modo de relleno y el estado de reproducción controlan diferentes partes de ese comportamiento.

Distingue entre transiciones y animaciones con keyframes

estándar transición animación
condición de inicio Cuando el valor cambia debido a hover, focus, cambio de clase, etc. Después de que la animación se aplica y ha pasado el tiempo de retraso,
definición de estado Valores CSS antes y después del cambio Especificar valores de inicio, medio y fin en keyframes
repetición y dirección Proceder con los cambios de estado Especificar por separado el número de veces, dirección y estado de detención

Una transición suele bastar para cambiar el color de fondo de un botón entre dos estados. Puedes usar animaciones para efectos como cuando aparece una notificación por primera vez o para una explicación visual que pase por varios pasos. Controlar la misma propiedad en el mismo elemento con dos funciones simultáneamente hace que sea difícil seguir cuál valor se aplica, así que para este ejercicio dividimos los roles. Si los efectos antes y después del cambio de estado son suficientes, considera comenzar con una transición simple como se explica en transformaciones y transiciones con CSS.

Define fotogramas clave y configuraciones de reproducción

En el fotograma clave, from corresponde a 0%, y to corresponde a 100%. Si necesitas un estado intermedio, añade un porcentaje de progreso como 50%. Solo declarar un nombre de fotograma clave no hará que se reproduzca; debes asociarlo con el animation-name del elemento.

@keyframes travel {
  0% { transform: translateX(0); }
  50% { transform: translateX(3rem); }
  100% { transform: translateX(6rem); }
}
.marker { animation: travel 4s linear 1s 1 normal forwards; }

Este código parcial es una versión abreviada del fotograma clave y la configuración .marker del mismo nombre en el ejemplo completo a continuación. 4s es el tiempo que tarda en reproducirse una vez y 1s es el retraso de inicio. Si no se especifica la duración, el valor predeterminado es 0 segundos, lo que dificulta observar el proceso de movimiento. Puedes reducir la confusión sobre el tiempo y la frecuencia dividiéndolo en propiedades detalladas al principio.

Propiedad Valores para este ejemplo Cosas a cambiar
animation-duration 4s un tiempo de reproducción
animation-timing-function linear Diferencia entre progreso constante y curva ease
animation-delay 1s Tiempo de espera antes de comenzar
animation-iteration-count 1 número de reproducciones; infinite repite sin límite
animation-direction normal Reproducción hacia adelante/hacia atrás/alternada
animation-fill-mode forwards Valor a aplicar durante el tiempo fuera de reproducción
animation-play-state running predeterminado Pausa el progreso actual con paused

Aunque los porcentajes de los fotogramas estén espaciados por igual, la función de temporización modifica cómo cambia la posición dentro de cada tramo. Este ejercicio utiliza linear, lo que facilita verificar las posiciones intermedias. Para la creación y conexión de fotogramas clave, consulta el documento MDN @keyframes.

Compara la dirección, el número de iteraciones y el modo de relleno

normal procede desde el principio hasta el final, y reverse procede desde el final hasta el principio. alternate se reproduce alternativamente en dirección hacia adelante la primera vez y en dirección inversa la siguiente vez. Si el número de iteraciones es 2 y la dirección es alternate, la última llegará al primer fotograma clave.

forwards no es una configuración que siempre conserve siempre el fotograma del 100%. Dependiendo de la dirección de reproducción y del número de veces, se mantiene el valor del último fotograma clave realmente alcanzado. En el ejemplo, una vez en la dirección hacia adelante mantiene la posición de 6rem, una vez en la dirección inversa mantiene la posición de 0, y dos veces en la dirección alterna también mantiene la posición de 0. Esta descripción se basa en un número entero de reproducciones completas, un número fraccionario puede terminar a medio progreso. la descripción de animation-fill-mode de MDN resume las condiciones de cada dirección .

fill-mode Durante la espera inicial Después de finalizar
none CSS básico CSS básico
forwards CSS básico Último fotograma clave reproducido
backwards Fotograma clave para reproducir primero CSS básico
both Fotograma clave para reproducir primero Último fotograma clave reproducido

Si el valor CSS base y el valor final del fotograma clave son los mismos, la diferencia entre none y forwards puede ser invisible. La caja de movimiento de abajo tiene una posición predeterminada de 1rem, un inicio de 0 y un final de 6rem para mostrar la diferencia. Por otro lado, el aviso que debe leerse tiene un estilo base visible y completo incluso cuando se elimina su animación.

Ejecuta y cambia una configuración a la vez

Guarda el siguiente código como animation-lab.html en UTF-8 y ábrelo en tu navegador. El aviso superior tiene una breve animación de entrada y permanece visible, y la caja decorativa inferior comienza a moverse después de 1 segundo y se mueve durante 4 segundos. Después de modificar los valores, guarda el archivo y recarga la página para comparar desde el principio.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Keyframes and end states exercise</title>
  <style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1rem; color: #183044; font-family: sans-serif; line-height: 1.6; }
main { max-width: 46rem; margin-inline: auto; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.2rem; }
button, input { font: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 3px solid #164f73; outline-offset: 3px; }
.notice { padding: 1rem; border: 1px solid #90bdd8; border-radius: .5rem; background: #eaf4fa;
  opacity: 1; transform: none; animation: appear 400ms ease-out; }
@keyframes appear {
  from { opacity: 0; transform: translateY(.5rem); }
  to { opacity: 1; transform: translateY(0); }
}
.track { margin-block: 1rem; padding: 1rem; border: 2px dashed #8a9ba7; }
.marker { width: 2rem; height: 2rem; border-radius: .25rem; background: #166b92;
  transform: translateX(1rem);
  animation-name: travel; animation-duration: 4s; animation-timing-function: linear;
  animation-delay: 1s; animation-iteration-count: 1; animation-direction: normal;
  animation-fill-mode: forwards; }
@keyframes travel {
  0% { transform: translateX(0); background-color: #166b92; }
  50% { transform: translateX(3rem); background-color: #6a3989; }
  100% { transform: translateX(6rem); background-color: #28633b; }
}
#pause:checked ~ .track .marker { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .notice, .marker { animation: none; }
}
  </style>
</head>
<body>
<main>
<h1>Check entrance and movement</h1>
<p class="notice">This notice remains readable without animation.</p>
<h2>Comparing end states</h2>
<p>Movement starts one second after loading. Refresh the page to compare again.</p>
<input id="pause" type="checkbox"><label for="pause">Pause movement</label>
<div class="track"><div class="marker" aria-hidden="true"></div></div>
<p>The colors and movement are decorative. Essential information remains available independently of the animation, as in this sentence.</p>
</main>
</body>
</html>
  1. En la configuración predeterminada, la caja está en la posición 1rem durante la demora, se mueve a 0 al inicio y permanece en la posición 6rem al finalizar. Verifica la diferencia entre el valor de demora y el valor inicial.
  2. Cambia solo animation-fill-mode a none y actualiza. Una vez terminado, regresa a la posición predeterminada de 1rem y al color azul predeterminado. Restaura forwards.
  3. Cambia solo fill-mode a both. La posición inicial 0 se aplica incluso durante las demoras. Tras la confirmación, restaura forwards.
  4. Deja el conteo como 1 y cambia la dirección a reverse. Después de completar, verifica que la posición 0 permanezca y restaura a normal.
  5. Verifica los resultados cambiando la dirección a alternate y manteniendo el conteo en 1. En ese estado, si cambias el número a 2, se producirá una segunda reproducción. Después de la confirmación, el conteo es 1 y la dirección se restablece a normal.
  6. Inmediatamente después de actualizar, activa la casilla Pause movement y espera un momento. Si la cancelas, continuarás desde donde lo dejaste. Esto es diferente de la capacidad de reproducir desde el principio.

Mantén el contenido visible con movimiento reducido

La configuración reducida elimina la animación de las cajas de orientación y decoración. Las instrucciones siguen siendo legibles ya que el valor predeterminado es opacity: 1 y la caja aparece en la posición predeterminada de 1rem. Dejar el estado legible solo en los fotogramas clave finales o en forwards puede hacer que el contenido desaparezca en ausencia de animación.

Activa la reducción de movimiento reducido en el panel Rendering de DevTools o en el sistema operativo y recarga. Ambos elementos deben permanecer quietos mientras su contenido sigue siendo visible. Consulta la guía MDN prefers-reduced-motion y después restaura la configuración de emulación después de la comparación. Además, sigue comprobaciones del diseño adaptable con anchura, zoom y teclado para comprobar el recorte y la usabilidad con el movimiento desactivado.

Antes de agregar repetición infinita, decide por qué se necesita movimiento y cómo se detendrá. Este ejemplo utiliza iteraciones finitas y proporciona información importante independientemente del movimiento y el color. Si nada se mueve, comprueba el nombre de la animación, la duración y la condición de movimiento reducido. Para un estado final inesperado, compara la dirección, el número de iteraciones, el modo de llenado y el CSS subyacente.