CSS: Animaciones

Las animaciones CSS permiten crear efectos de movimiento entre dos estilos diferentes de un elemento HTML, pasando por distintas fases intermedias, y sin necesidad de usar JavaScript. Además, se pueden iniciar sin que el usuario realice una acción concreta. Por tanto, son más potentes que las transiciones.

La principal ventaja de las animaciones frente a las transiciones es que usan fotogramas (keyframes) para indicar el estado inicial, el estado final y los puntos intermedios necesarios para obtener la secuencia deseada. Además, las animaciones son fáciles de usar, incluso sin conocer JavaScript.

Otra importante ventaja de usar animaciones es que se muestran correctamente en cualquier equipo, incluso en ordenadores poco potentes. El navegador web controla la secuencia de animación, optimizando el rendimiento de la misma.

Las animaciones están compuestas por dos componentes: las propiedades CSS que permiten describir la animación en los elementos HTML, y una secuencia de fotogramas definidos con la regla arroba @keyframes.

Propiedades descritas en este artículo:

Propiedad Descripción
animation-name Indica el nombre de la animación.
animation-duration Indica la duración de la animación.
animation-timing-function Indica la función de animación.
animation-delay Indica el tiempo de espera.
animation-iteration-count Indica las veces que se repetirá.
animation-direction Indica la dirección de la animación.
animation-fill-mode Controla la aplicación de estilos.
animation-play-state Indica el estado de la animación.
animation-composition Mezcla varias animaciones.
animation Abreviatura de todas las anteriores.

Antes de conocer cada una de estas propiedades CSS, vamos a ver un ejemplo llamado “muestra” en el que un rectángulo naranja se desplaza a la derecha, se deforma hacia un lado, cambia de color, se deforma hacia el otro lado, cambia de color otra vez y luego recupera su aspecto original mientras regresa.

Código CSS:

.rectangulo {
  animation: muestra 4s infinite;
  height: 30px;
  position: relative;
  width: 80px;
}

@keyframes muestra {
  0% {
    background: #ff7f2a;
    left: 0;
  }

  33% {
    background: teal;
    left: 30px;
    transform: skewX(-35deg);
  }

  67% {
    background: mediumpurple;
    left: 30px;
    transform: skewX(35deg);
  }

  100% {
    background: #ff7f2a;
    left: 0;
    transform: skewX(0);
  }
}

Resultado:

La regla arroba ‘@keyframes’

Una animación está formada por una cierta cantidad de fotogramas, que mostrados secuencialmente uno detrás de otro, generan el efecto óptico de movimiento. Así es como se forma una animación, tanto en el cine como en Internet.

Cuando trabajamos con CSS, los fotogramas se forman durante el cambio entre dos estilos de un elemento. Con las propiedades CSS se define un fotograma inicial, fotogramas intermedios y un estado final. La regla arroba @keyframes permite definir estos fotogramas clave que darán forma a la animación.

Cuando la animación comience a reproducirse, el navegador web será el encarado de que se generen todos los fotogramas restantes necesarios para que la animación se reproduzca de forma suave y sin saltos bruscos.

Esta es la sintaxis de @keyframes:

@keyframes identificador {
  selector-tiempo {
    propiedad: valor;
    propiedad: valor;
  }
}

Por ejemplo:

@keyframes nombre {
  0% { background: red; }
  50% { background: green; }
  100% { background: blue; }
}

El identificador será el nombre que identifica la animación. Este nombre es el que luego se usará en las propiedades CSS animation-name o animation para indicar el elemento HTML que debe animarse.

El selector de tiempo puede ser un valor numérico en porcentaje. También puede usarse las palabras clave from y to, para indicar un desplazamiento inicial de 0% o un desplazamiento final de 100%.

En el ejemplo siguiente, la animación indica un cambio de color de fondo. En el primer fotograma, el color de fondo es el rojo (red), mientras que en el segundo fotograma es el rojo oscuro (darkred).

@keyframes oscurece {
  from { background: red; }
  to { background: darkred; }
}

En este otro ejemplo, hacemos que un objeto se desplace de izquierda a derecha. En el primer fotograma, el objeto se encuentra a la izquierda, mientras que en el segundo fotograma se encuentra a la derecha.

@keyframes mueve {
  from {
    left: 0%;
  }
  to {
    left: 100%;
  }
}

No obstante, usar @keyframes no es suficiente para que la animación que hemos definido se reproduzca. El nombre de la animación debe asociarse a uno o varios elementos HTML. También debe indicarse la duración de la animación, y de forma opcional, puede indicarse otras configuraciones. A continuación se describen las propiedades CSS para configurar la reproducción de la animación.

La propiedad ‘animation-name’

La propiedad animation-name permite especificar el nombre de la animación que se aplicará al elemento seleccionado. El nombre debe ser el mismo que el identificador utilizado en la regla arroba @keyframes.

Las animaciones pueden ser múltiples, por lo que es posible indicar varios nombres separados mediante una coma. Si el nombre (identificador) especificado no coincide con el de ninguna @keyframe, no se aplicará ninguna animación.

El valor por defecto es la palabra clave none, que además se puede usar para desactivar una animación sin alterar el orden de los demás identificadores, o para desactivar animaciones en un momento dado.

El nombre que identifica la animación puede estar en mayúsculas o minúsculas, de la “a” a la “z”, pueden contener números del “0” al “9”, guiones bajos (“_”) y guiones medios (“-“). El primer carácter debe ser una letra.

Ejemplos de uso de animation-name:

.ejemplo {
  animation-name: mi-secuencia;
}

.ejemplo {
  animation-name: Mueve1, Mueve2;
}

.ejemplo {
  animation-name: uno, dos, tres;
}

.ejemplo {
  animation-name: none;
}

La propiedad ‘animation-duration’

La propiedad animation-duration permite indicar la duración de la animación, es decir, el tiempo que tarda en completar un ciclo. Puede indicarse una lista de tiempos, separados por una coma.

Los valores de esta propiedad serán en unidades de tiempo, pudiendo usar segundos (s) o milisegundos (ms). Por defecto, el valor es de 0s. No se permite usar valores en negativo, por tanto deberán ser positivos.

Ejemplos de uso de animation-duration:

.ejemplo {
  animation-duration: 2s;
}

.ejemplo {
  animation-duration: 0.5s, 0.25s;
}

.ejemplo {
  animation-duration: 10ms, 20ms, 30ms;
}

.ejemplo {
  animation-duration: 0s;
}

A continuación veremos unos objetos que se desplazan de izquierda a derecha, pero con distintas velocidades. El primero tarda 6 segundos, el segundo tarda 4 segundos y el tercero solo 2 segundos.

.lento {
  animation-duration: 6s;
}

.normal {
  animation-duration: 4s;
}

.rapido {
  animation-duration: 2s;
}

Resultado:

lento

normal

rápido

El único valor que cambia entre estos objetos que se encuentran en movimiento es la duración. Presiona encima para poner la pausa.

La propiedad ‘animation-timing-function’

La propiedad animation-timing-function permite especificar la función que se usará en la animación. Así se puede definir la aceleración o desaceleración de los pasos intermedios, como si fuera una función matemática.

Existe una serie de palabras clave que definen las principales funciones de velocidad. Por ejemplo, para indicar una velocidad constante (sin aceleración) se usa la palabra clave linear. En cambio, para indicar una velocidad lenta que acelere al final se usa la palabra clave ease-in.

A continuación se exponen las funciones predefinidas que CSS provee para modificar la velocidad de la animación:

Valor Inicio Medio Final
ease Lento Rápido Lento
linear Normal Normal Normal
ease-in Lento Normal Normal
ease-out Normal Normal Lento
ease-in-out Lento Normal Lento

Por defecto se usa la función ease, con la que la animación empieza lentamente, luego acelera y al final frena, terminando lentamente otra vez. Se trata de una función simétrica: lenta en los extremos y rápida al centro.

Vamos a visualizar varios ejemplos a la vez para comprender mejor la diferencia que se produce al animar un elemento usando cada una de las funciones mencionadas. Creamos algunos objetos que irán de un lado al otro.

El código es el siguiente:

.ease {
  animation-timing-function: ease;
}

.linear {
  animation-timing-function: linear;
}

.ease-in {
  animation-timing-function: ease-in;
}

.ease-out {
  animation-timing-function: ease-out;
}

.ease-in-out {
  animation-timing-function: ease-in-out;
}

Resultado

ease

linear

ease-in

ease-out

ease-in-out

En esta ocasión, se puede observar que los 5 objetos llegan al mismo tiempo, en 3 segundos (3s), aunque aparentemente no lo parezca. Presiona sobre ellos para que se queden pausados.

La función ‘cubic-bezier()’

Mediante la función cubic-bezier() se puede crear una función de aceleración personalizada. Esto se consigue a partir de la descripción de dos puntos de control indicados mediante dos coordenadas para cada uno. Por tanto, tendremos cuatro coordenadas: dos para el primer punto y dos para el segundo.

Puntos Significado
x1 Coordenada X del primer punto de control.
y1 Coordenada Y del primer punto de control.
x2 Coordenada X del segundo punto de control.
y2 Coordenada Y del segundo punto de control.

Esta es la sintaxis de la función cubic-bezier():

cubic-bezier(x1, y1, x2, y2);

Por ejemplo:

.ejemplo {
  animation-timing-function:
    cubic-bezier(0.8, 0, 0.2, 1);
}

Tal y como se puede observar en el ejemplo anterior, los valores serán numéricos, admitiendo decimales; pueden ser positivos o negativos.

A continuación se crea dos nuevos objetos que se desplazan de izquierda a derecha, usando dos funciones personalizadas mediante la función cubic-bezier(). Los dos ejemplos son ligeramente diferentes.

Código CSS

.cubic1 {
  animation-timing-function:
    cubic-bezier(0, 0, 0, 0.4);
}

.cubic2 {
  animation-timing-function:
    cubic-bezier(0, 0, 0.4, 0);
}

Resultado:

Objeto 1

Objeto 2

La aceleración de los dos objetos varía de forma distinta. Aparentemente, uno parece más rápido que el otro, pero ambos llegan a su destino en 3 segundos. Presiona sobre ellos para que se queden pausados.

La función ‘steps()’

La función steps() permite crear otro tipo de animación en la que no se produce un cambio entre estados de forma suave y gradual, sino en saltos bruscos y de forma escalonada. Permite indicar el número de saltos deseados.

Imaginemos que queremos realizar una animación producida en 5 pasos. El tiempo que dure la animación se dividirá entre 5, produciendo un salto en el momento del 20%, otro en el 40%, otro en el 60%, otro en el 80% y el último en el 100% del tiempo. Realizando 5 paradas desde el inicio hasta el final.

En esta función puede indicarse un segundo parámetro opcional, que permite especificar si el salto brusco de la animación debe producirse al principio o al final de cada paso. La palabra clave start indica que el salto ocurre al principio de cada salto; y con la palabra clave end (por defecto) ocurre al final.

Esta es la sintaxis de la función steps():

steps(n, start|end);

Por ejemplo:

.ejemplo {
  animation-timing-function:
    steps(5, end);
}

Vamos a visualizar un nuevo ejemplo. Esta esta vez, comparando una función lineal (linear), que se desplaza suavemente, con la función steps(), que se desplaza realizando concretamente 10 saltos bruscos.

.steps {
  animation-timing-function:
    steps(10, start);
}

Resultado:

linear

steps

Ambos objetos tienen una duración de 3 segundos, y solo les diferencia el hecho de que usan funciones de tiempo diferentes.

La propiedad ‘animation-delay’

La propiedad animation-delay permite especificar el tiempo de retraso que debe transcurrir antes de iniciar la animación deseada. Por tanto, con esta propiedad se retarda el inicio de la secuencia de animación.

Para indicar que la animación comience de inmediato debe usarse el valor 0s (0 segundos), que es además el valor por defecto. Si se indica el valor 2s (2 segundos), la secuencia se iniciará después de 2 segundos.

Esta propiedad admite valores negativos, con los que la animación se iniciará de inmediato, pero no desde el principio, sino a partir del punto indicado. Si se indica -2s (-2 segundos), la secuencia se iniciará de forma inmediata, pero a partir del fotograma correspondiente a los 2 segundos.

Ejemplos de uso de animation-delay:

.ejemplo {
  animation-delay: 3s;
}

.ejemplo {
  animation-delay: -1s;
}

.ejemplo {
  animation-delay: 320ms;
}

La propiedad ‘animation-iteration-count’

La propiedad animation-iteration-count permite especificar el número de veces que debe repetirse la animación. De esta manera, se puede establecer un número limitado o incluso decirle que se repita hasta el infinito.

El valor por defecto es 1, con el que la animación se produce una única vez y se detiene. No se permite valores negativos, como es lógico, pero sí que se puede indicar valores con decimales. Por ejemplo, 0.5 se realizará la mitad de la animación. Con el valor infinite se repetirá para siempre.

Ejemplos de uso de animation-iteration-count:

.ejemplo {
  animation-iteration-count: 3;
}

.ejemplo {
  animation-iteration-count: 0.2;
}

.ejemplo {
  animation-iteration-count: infinite;
}

La propiedad ‘animation-direction’

La propiedad animation-direction permite indicar la dirección de la animación, es decir, si tras finalizar la secuencia debe retroceder hasta el fotograma inicial o si debe comenzar desde el principio otra vez.

Esta propiedad es realmente útil para lograr efectos de retorno de forma automática sin tener que indicarlo en la secuencia de animación del @keyframe. Por ejemplo, si movemos un elemento hacia la derecha y queremos animar su regreso, será tan sencillo como indicarlo a través de esta propiedad.

Lista de valores posibles:

Valor Descripción
normal La animación avanza en orden normal.
reverse La animación avanza en orden inverso.
alternate Inicia en orden normal y luego retrocede.
alternate-reverse Inicia en orden inverso y luego en orden normal.

Ejemplos de uso de animation-direction:

.ejemplo {
  animation-direction: reverse;
}

.ejemplo {
  animation-direction: alternate;
}

.ejemplo {
  animation-direction: alternate-reverse;
}

La propiedad ‘animation-fill-mode’

La propiedad animation-fill-mode permite indicar el modo en el que se aplicarán los estilos CSS al elemento, antes y después de que se produzca la animación. Por tanto, esta propiedad es útil para controlar el estado de los elementos antes de que se inicie la animación y después de que haya finalizado.

Como opción por defecto de las animaciones, no aplican estilos antes de iniciar y después de finalizar. Esto puede verse en el hecho de que la apariencia de un elemento regresa a su estado inicial cuando la animación finaliza.

Lista de valores posibles de la propiedad animation-fill-mode para indicar el comportamiento de la animación cuando no se reproduce:

Valor Descripción
none No se aplica estilos antes y después.
backwards Aplica estilos del fotograma inicial.
forwards Aplica estilos del fotograma final.
both Aplica estilos de los fotogramas inicial y final.

Ejemplos de uso de animation-fill-mode:

.ejemplo {
  animation-fill-mode: backwards;
}

.ejemplo {
  animation-fill-mode: forwards;
}

.ejemplo {
  animation-fill-mode: both;
}

La propiedad ‘animation-play-state’

La propiedad animation-play-state permite indicar el estado de reproducción de una animación, es decir, si debe estar pausada o si debe estar reproduciéndose. Esta propiedad puede ser útil en CSS y en JavaScript. Por ejemplo, puede usarse con una pseudoclase (:hover o :active) para pausar o continuar.

Esta propiedad puede tener dos valores:

Valor Descripción
running La animación se reproduce. Por defecto.
paused La animación se queda pausada.

Ejemplos de uso de animation-play-state:

.ejemplo {
  animation-play-state: running;
}

.ejemplo {
  animation-play-state: paused;
}

La propiedad ‘animation-composition’

La propiedad animation-composition permite indicar al navegador la forma de aplicar las múltiples animaciones, en caso de que varias estén especificadas de forma encadenada. Por tanto, permite indicar cómo se mezclan. El valor por defecto es replace, en el que las animaciones se sobreescriben.

Esta propiedad puede tener tres valores:

Valor Descripción
replace Las animaciones se sobreescriben. Por defecto.
add Las animaciones se añaden.
accumulate Las animaciones se acumulan.

Ejemplos de uso de animation-composition:

.ejemplo {
  animation-composition: replace;
}

.ejemplo {
  animation-composition: add;
}

.ejemplo {
  animation-composition: accumulate;
}

La propiedad ‘animation’

La propiedad animation es una abreviatura (shorthand) que unifica todas las anteriores. Los valores de cada una de las propiedades anteriores deben estar separados por un espacio. El orden debe ser el siguiente:

  1. animation-name
  2. animation-duration
  3. animation-timing-function
  4. animation-delay
  5. animation-iteration-count
  6. animation-direction
  7. animation-fill-mode
  8. animation-play-state

Es importante no olvidar las unidades de las propiedades de tiempo: segundos (s) y milisegundos (ms). De lo contrario, se interpretará como el número de veces que debe repetirse la iteración de la animación.

Por ejemplo:

.ejemplo {
  animation: mueve 6s infinite;
}

.ejemplo {
  animation: mueve 250ms linear alternate;
}

.ejemplo {
  animation:
    mueve      /* nombre */
    0.4s       /* duración */
    linear     /* función */
    100ms      /* retraso */
    3          /* iteraciones */
    alternate  /* dirección */
    both       /* modo de estilos */
    paused;    /* estado */
}

Múltiples animaciones

CSS permite declarar múltiples animaciones para definirlas en una sola vez, a través de la propiedad abreviada animation. Para ello, solo hay que separar los distintos grupos de valores de esta propiedad con una coma.

En este ejemplo declaramos cuatro animaciones a la vez.

.multiples {
  animation:
    mueve 2s linear infinite,
    pinta 1s ease-out infinite,
    salta 200ms steps(4) 3,
    amaga 0.5s ease-in paused;
}

Estas animaciones iniciarán al mismo momento, pero tienen una duración distinta. La última no empezaría hasta que su estado se convierta a running, ya que de inicio está en pausa.

Encadenar animaciones

Usando la propiedad animation-delay con cierta perspicacia es posible encadenar múltiples animaciones, de modo que al terminar una empiece la otra. Es un truco muy sencillo de aplicar. Se trata de retardar la siguiente animación lo que duran las animaciones anteriores, en su conjunto.

Vamos a ver un ejemplo:

.multiples {
  animation:
    mueve 250ms linear,
    pinta 300ms linear 250ms,
    salta 450ms linear 550ms;
}

Debido a que la primera animación dura 250 milisegundos, el inicio de la segunda se retrasa la misma duración. Por su parte, la segunda dura 300 milisegundos, por tanto, la tercera se retrasará el tiempo de la duración de las dos animaciones anteriores, equivalente a 550 milisegundos.

← Artículo anterior
Artículo siguiente →