Usando animaciones CSS

Esta es una tecnolog铆a experimental
Comprueba la Tabla de compabilidad de navegadores cuidadosamente antes de usarla en producci贸n.

Las animaciones CSS3 permiten animar la transici贸n entre un estilo CSS y otro. Las animaciones constan de dos componentes: un estilo que describe la animaci贸n CSS y un conjunto de fotogramas que indican su estado inicial y final, as铆 como posibles puntos intermedios en la misma.

Las animaciones CSS tienen tres ventajas principales sobre las t茅cnicas tradicionales de animaci贸n basada en scripts:

  1. Son muy f谩ciles de usar para animaciones sencillas, puedes hacerlo incluso sin tener conocimientos de Javascript.
  2. La animaci贸n se muestra correctamente, incluso en equipos poco potentes. Animaciones simples realizadas en Javascript pueden verse mal (a menos que est茅n muy bien hechas). El motor de renderizado puede usar t茅cnicas de optimizaci贸n como el "frame-skipping" u otras t茅cnicas para que la ejecuci贸n de la animaci贸n se vea tan suave como sea posible.
  3. Al ser el navegador quien controle la secuencia de la animaci贸n, permitimos que optimice el rendimiento y eficiencia de la misma, por ejemplo, reduciendo la frecuencia de actualizaci贸n de la animaci贸n ejecut谩ndola en pesta帽as que no est茅n visibles.

Configurando la animaci贸n

Para crear una secuencia de animaci贸n CSS, t煤 estilizar谩s el elemento que quieras animar con la propiedad animation y sus sub-propiedades. Con ellas podemos no solo configurar el ritmo y la duraci贸n de la animaci贸n sino otros detalles sobre la secuencia de la animaci贸n. Con ellas no configuramos la apariencia actual de la animaci贸n, para ello disponemos de @keyframes como describiremos m谩s adelante .

Las subpropiedades de animation son:

animation-delay
Tiempo de retardo entre el momento en que el elemento se carga y el comienzo de la secuencia de la animaci贸n.
animation-direction
Indica si la animaci贸n debe retroceder hasta el fotograma de inicio al finalizar la secuencia o si debe comenzar desde el principio al llegar al final.
animation-duration
Indica la cantidad de tiempo que la animaci贸n consume en completar su ciclo (duraci贸n).
animation-iteration-count
El n煤mero de veces que se repite. Podemos indicar infinite para repetir la animaci贸n indefinidamente.
animation-name
Especifica el nombre de la regla @keyframes que describe los fotogramas de la animaci贸n.
animation-play-state
Permite pausar y reanudar la secuencia de la animaci贸n
animation-timing-function
Indica el ritmo de la animaci贸n, es decir, como se muestran los fotogramas de la animaci贸n, estableciendo curvas de aceleraci贸n.
animation-fill-mode
Especifica qu茅 valores tendr谩n las propiedades despu茅s de finalizar la animaci贸n (los de antes de ejecutarla, los del 煤ltimo fotograma de la animaci贸n o ambos).

Definiendo la secuencia de la animaci贸n con fotogramas

Una vez configurado el tiempo de la animaci贸n, necesitamos definir su apariencia. Esto lo haremos estableciendo dos fotogramas m谩s usando la regla @keyframes. Cada fotograma describe c贸mo se muestra cada elemento animado en un momento dado durante la secuencia de la animaci贸n.

Desde que se define el tiempo y el ritmo de la animaci贸n, el fotograma usa percentage para indicar en qu茅 momento de la secuencia de la animaci贸n tiene lugar. 0% es el principio, 100% es el estado final de la animaci贸n. Debemos especificar estos dos momentos para que el navegador sepa d贸nde debe comenzar y finalizar; debido a su importancias, estos dos momentos tienen alias especiales: from y to.

Adem谩s puedes, opcionalmente, incluir fotogramas que describan pasos intermedios entre el punto inicial y final de la animaci贸n.

Ejemplos

Nota: Los siguientes ejemplos no usan ning煤n prefijo en las propiedades CSS de animaci贸n. Los navegadores antiguos pueden necesitarlos. Al hacer click en "Ver el ejemplo vivo" se incluye el prefijo -webkit.

Haciendo que un texto se delice por la ventana del navegador

Este sencillo ejemplo da estilos al elemento <p> para que el texto se deslice por la pantalla entrando desde el borde derecho de la ventana del navegador.

Animaciones como esta pueden hacer que la p谩gina se vuelva m谩s ancha que la ventana del navegador. Para evitar este problema, pon el elemento que ser谩 animado en un contenedor y agrega overflow:hidden en el contenedor.

p {
  animation-duration: 3s;
  animation-name: slidein;
}

@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}

El estilo del elemento <p> especifica, a trav茅s de la propiedad animation-duration, que la animaci贸n debe durar 3 segundos desde el inicio al fin y que el nombre de los @keyframes que definen los fotogramas de la secuencia de la animaci贸n es "slidein".

Si queremos a帽adir alg煤n estilo personalizado sobre el elemento <p> para usarlo en navegadores que no soporten animaciones CSS, tambi茅n podemos incluirlos. En nuestro ejemplo, no queremos ning煤n otro estilo personalizado diferente al efecto de la animaci贸n.

Los fotogramas se definen usando la regla @keyframes. En nuestro ejemplo, tenemos solo dos fotogramas. El primero de ellos sucede en elt 0% (hemos usado su alias from). Aqui, configuramos el margen izquierdo del elemento, poniendolo al 100%  (es decir, en el borde derecho del elemento contenedor), y su ancho al 300% (o tres veces el ancho del elemento contenedor). Esto hace que en el primer fotograma de la animaci贸n tengamos el encabezado fuera del borde derecho de la ventana del navegador.

El segundo (y 煤ltimo) fotograma sucede en el 100% (hemos usado su alias to). Hemos puesto el margen derecho al 0% y el ancho del elemento al 100%. Esto produce que el encabezado, al finalizar la animaci贸n, est茅 en el borde derecho del 谩rea de contenido.

<p>The Caterpillar and Alice looked at each other for some time in silence:
at last the Caterpillar took the hookah out of its mouth, and addressed
her in a languid, sleepy voice.</p>

(Recarga la p谩gina para ver la animaci贸n, o haz click en el bot贸n CodePen para ver la animaci贸n en CodePen)

A帽adiendo otro fotograma

Vamos a a帽adir otro fotograma a la animaci贸n de nuestro ejemplo anterior. Pongamos que queremos que el tama帽o de fuente del encabezado aumente a medida que se mueve durante un tiempo y que despu茅s disminuye hasta su tama帽o original. Esto es tan sencillo como a帽adir este fotograma:

75% {
  font-size: 300%;
  margin-left: 25%;
  width: 150%;
}

Esto le dice al navegador que en el 75% de la secuencia de la animaci贸n, el encabezado tiene un margen izquierdo del 25%, un tama帽o de letra del 200% y un ancho del 150%.

(Recarga la p谩gina para ver la animaci贸n, o haz click al bot贸n de CodePen para la animaci贸n en CodePen)

Haciendo que se repita

Para hacer que la animaci贸n se repita, solo hay que usar la propiedad animation-iteration-count e indicarle cu谩ntas veces debe repetirse. En nuestro caso, usamos  infinite para que la animaci贸n se repita indefinidamente:

p {
  animation-duration: 3s;
  animation-name: slidein;
  animation-iteration-count: infinite;
}

Moviendolo hacia adelante y hacia atr谩s

Hemos hecho que se repita, pero queda un poco raro que salte al inicio de la animaci贸n cada vez que 茅sta comienza. Queremos que se mueva hacia adelante y hacia atr谩s en la pantalla. Esto lo conseguimos f谩cilmente indicando que animation-direction es alternate:

p {
  animation-duration: 3s;
  animation-name: slidein;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

Usando la versi贸n abreviada animation

La versi贸n abreviada animation es usado para ahorrar espacio. Por ejemplo, la regla que hemos usado en este art铆culo:

p {
  animation-duration: 3s;
  animation-name: slidein;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

Se puede reemplazar por

p {
  animation: 3s infinite alternate slidein;
}

Nota: Puedes encontrar m谩s detalles en la p谩gina de referencia animation 

Estableciendo multiples valores de propiedades animation

Las propiedades de la versi贸n larga de animation pueden aceptar m煤ltiples valores, separados por comas - esta caracter铆stica puede ser usada cuando quieres aplicar m煤ltiples animaciones en una solo regla, y establecer por separado duration, iteration-count, etc. para diferentes animaciones. Vamos a ver algunos ejemplos r谩pidos para explicar las diferentes combinaciones:

En el primer ejemplo, tenemos tres nombres de animaci贸n establecidos, pero solo una duraci贸n (duration) y n煤mero de iteraciones (iteration-count). En este caso, a las tres animaciones se les da la misma duraci贸n y n煤mero de iteraciones:

animation-name: fadeInOut, moveLeft300px, bounce;
animation-duration: 3s;
animation-iteration-count: 1;

En el segundo ejemplo, tenemos tres valores establecidos en las tres propiedades. En este caso, cada animaci贸n se ejecuta con los valores correspondientes en la misma posici贸n en cada propiedad, as铆 por ejemplo fadeInOut tiene una duraci贸n de 2.5s y 2 iteraciones, etc.

animation-name: fadeInOut, moveLeft300px, bounce;
animation-duration: 2.5s, 5s, 1s;
animation-iteration-count: 2, 1, 5;

En el tercer caso, hay tres animaciones especificadas, pero solo dos duraciones y n煤mero de iteraciones. En los casos en donde no hay valores suficientes para dar un valor separado a cada animaci贸n, los valores se repiten de inicio a fin. As铆 por ejemplo, fadeInOut obtiene una duraci贸n de 2.5s y moveLeft300px obtiene una duraci贸n de 5s. Ahora tenemos asignados todos los valores de duracion disponibles, as铆 que empezamos desde el inicio de nuevo - por lo tanto bounce  tiene una duraci贸n de 2.5s. El n煤mero de iteraciones (y cualquier otra propiedad que especifiques) ser谩 asignados de la misma forma.

animation-name: fadeInOut, moveLeft300px, bounce;
animation-duration: 2.5s, 5s;
animation-iteration-count: 2, 1;

Usando eventos de animaci贸n

Podemos tener un control mayor sobre las animaciones (as铆 como informaci贸n 煤til sobre ellas) haciendo uso de eventos de animaci贸n. Dichos eventos, representados por el objeto AnimationEvent , se pueden usar para detectar cu谩ndo comienza la animaci贸n, cu谩ndo termina y cu谩ndo comienza una iteraci贸n. Cada evento incluye el momento en el que ocurri贸, as铆 como el nombre de la animaci贸n que lo desencaden贸.

Vamos a modificar el ejemplo del texto deslizante para recoger informaci贸n sobre cada evento cuando suceda y asi podremos echar un vistazo a c贸mo funcionan.

Agregando CSS

Empezamos creando el CSS para la animaci贸n. Esta animaci贸n durar谩 3 segundos, se llama slidein, se repite 3 veces, y alterna de direcci贸n cada vez. En @keyframes, width y margin-left son manipulados para hacer que el elemento se deslice por la pantalla.

.slidein {
  animation-duration: 3s;
  animation-name: slidein;
  animation-iteration-count: 3;
  animation-direction: alternate;
}

@keyframes slidein {
  from {
    margin-left:100%;
    width:300%
  }

  to {
   margin-left:0%;
   width:100%;
 }
}

A帽adiendo detectores de eventos a la animaci贸n

Usaremos un poco de Javascript para escuchar los tres posibles eventos de animaci贸n. Este c贸digo configura nuestros detectores de eventos (event listeners); los llamamos cuando el documento carga por primera vez para configurar todo.

var e = document.getElementById("watchme");
e.addEventListener("animationstart", listener, false);
e.addEventListener("animationend", listener, false);
e.addEventListener("animationiteration", listener, false);

e.className = "slidein";

Es la forma est谩ndar de detectar eventos en Javascript, si quieres conocer m谩s detalles sobre c贸mo funciona la detecci贸n de eventos, consulta la documentaci贸n de element.addEventListener().

La 煤ltima l铆nea pone la clase slidein al elemento para comenzar la animaci贸n. 驴Por qu茅?. Porque que el evento animationstart se dispara cuando comienza la animaci贸n y, en nuestro caso, esto suceder铆a antes de que nuestro c贸digo se hubiera ejecutado y no podr铆amos crear los detectores de eventos. Para evitarlo, creamos los detectores de eventos antes y a帽adimos la clase al elemento para iniciar la animaci贸n.

Recibiendo los eventos

Los eventos, al irse disparando, llamar谩n a la funci贸n listener().

function listener(e) {
  var l = document.createElement("li");
  switch(e.type) {
    case "animationstart":
      l.innerHTML = "Iniciado: tiempo transcurrido " + e.elapsedTime;
      break;
    case "animationend":
      l.innerHTML = "Finalizado: tiempo transcurrido " + e.elapsedTime;
      break;
    case "animationiteration":
      l.innerHTML = "Nueva iteraci贸n comenz贸 a los " + e.elapsedTime;
      break;
  }
  document.getElementById("output").appendChild(l);
}

Este c贸digo tambi茅n es muy sencillo. Miramos en event.type para saber qu茅 tipo de evento se ha disparado y, en funci贸n del tipo de evento, a帽adimos su correspodiente texto al elemento <ul> que usaremos para registrar la actividad de nuestros eventos.

El resultado, si todo ha ido bien, ser谩 algo parecido a esto:

  • Iniciado: tiempo transcurrido 0
  • Nueva iteraci贸n comenz贸 a los 3.01200008392334
  • Nueva iteraci贸n comenz贸 a los 6.00600004196167
  • Finalizado: tiempo transcurrido 9.234000205993652

Fij茅monos en que despues de la iteraci贸n final de la animaci贸n, el evento animationiteration no se env铆a, en su lugar se lanza animationend.

El HTML

Solo nos falta mostrar el c贸digo HTML necesario para mostrar el ejemplo en la p谩gina, incluyendo la lista en la que el script ir谩 insertando la informaci贸n de los eventos que se vayan disparando.

<h1 id="watchme">Watch me move</h1>
<p>
  This example shows how to use CSS animations to make <code>H1</code>
  elements move across the page.</p>
<p>
  In addition, we output some text each time an animation event fires,
  so you can see them in action.
</p>
<ul id="output">
</ul>

Te puede interesar tambi茅n