Animaciones con fotogramas clave en CSS

La propiedad transition de CSS para realizar animaciones es muy cómoda y fácil de usar, pero esa misma sencillez hace que no sean apropiadas si buscamos algunos efectos de animación más complejos. Eso es algo que podemos alcanzar si usamos las animaciones de CSS basadas en línea de tiempo.

Aunque son algo más complicadas de configurar que las transiciones, las animaciones por fotogramas clave tienen varias ventajas que las pueden convertir en el componente obligatorio con el que trabajar si estamos buscando alguna de estas características:

Definir una animación de tipo keyframe

Para construir la animación de este tipo se usa la directiva @keyframe seguida del nombre que le queremos dar a la animación. Y dentro de ella establecemos los diferentes fotogramas clave de nuestra línea de tiempo, especificando en cada uno de ellos qué propiedades cambian, con sus nuevos valores.

Estos fotogramas clave se expresan en porcentajes sobre el tiempo total de la animación. Es conveniente, pero no necesario, definir los fotogramas clave de inicio y final, que pueden ser expresados como 0% y 100% o usando las palabras clave from y to.

A medida que necesitemos cambiar valores de nuestra animación, añadimos el fotograma clave correspondiente, indicando su momento en la animación de forma porcentual, y estableciendo los nuevos valores para las propiedades deseadas. De este modo, añadiendo fotogramas clave, es como construimos nuestra línea de tiempo.

Así, declarar una animación para que mueva un elemento hacia la izquierda, desplazándose el espacio de su anchura sería algo así:

            
@keyframes desplaza { from { transform: translate(0, 0); } to { transform: translate(100%, 0); } }

Y si queremos que a mitad de animación cambie su color de fondo a naranja añadimos un nuevo fotograma clave así:

            
@keyframes desplaza { from { transform: translate(0, 0); } 50% { background: orange; } to { transform: translate(100%, 0); } }

O así

@keyframes desplaza { from { transform: translate(0, 0); } to { transform: translate(100%, 0); } 50% { background: orange; } }

Como vemos en el ejemplo, el orden en el que se definen los fotogramas no tiene que ser secuencial, podemos poner cualquier punto en cualquier momento. Pero si la animación va a tener cierta complejidad es preferible hacerlo de forma secuencial, de 0 a 100%, para que su edición nos resulte más cómoda.

Asignar una animación a un elemento

La animación definida en un @keyframe se vincula al elemento que queramos animar mediante la propiedad CSS animation-name dentro del selector CSS del elemento. Esto hace que las propiedades definidas en esos fotogramas se apliquen sobre el elemento según los intervalos de tiempo de la animación.

De este modo, para añadir la animación del ejemplo anterior a un elemento div que tiene aplicada la clase CSS cuadro, podríamos hacer algo así dentro de esa clase:

        
.muestra { width: 50%; height: 50px; background: violet; animation-name: desplaza; }

Pero esta propiedad únicamente no es suficiente para que la animación funcione. Es necesario definir, por lo menos, una segunda propiedad que establezca el tiempo que va a durar la animación. Es la propiedad animation-duration. Con estas dos definidas ya tendríamos una animación que se ejecuta de forma inmediata cuando sea leído y aplicado el CSS del elemento. Quedando algo así:

            
.muestra { width: 50%; height: 50px; background: violet; animation-name: desplaza; animation-duration: 3s; }

El resultado de la animación anterior sería este:

Propiedades de la animación

Para entender por completo este tipo de animaciones hay que saber que @keyframes solamente define el aspeto de los fotogramas clave. Es decir, qué cosas cambian en cada momento de la línea de tiempo, del elemento que vamos a animar. Pero no tiene propiedades que se refieran a la propia animación, como por ejemplo, la aceleración o el tiempo de retraso. Estas propiedades pertenecen al propio elemento que animamos, y se definen como las propiedades animation-name y animation-duration. Este es el listado completo de las propiedades disponibles para cualquier animación:

Modo abreviado

Como con muchas otras propiedades, CSS tiene una versión shorthand que resume las siete subpropiedades en la propiedad principal animation. Esta sería su notación: animation: name duration timing-function delay iteration-count direction fill-mode;. Y este es un ejemplo de la propiedad en modo abreviado:

animation: desplaza 10s ease-in-out 0s infinite alternate both;

Ejemplos

Vamos a usar la siguiente animación para aplicarla a los 3 elementos de la derecha, usando la clase del ejemplo. Además, para cada elemento definiremos distintas propiedades de animación para ver su resultado:


@keyframes grafico {
    from {
        height: 5px;
    }
    70% {
        background-color: darkgoldenrod;
    }
    to {
        height: 100%;
        box-shadow: 2px 2px 1px black;
        background-color: gold;
    }
}
                    

.barra {
    width: 150px;
    height: 5px;
    background: orange;
    position: absolute;
    bottom: 0;
    animation: grafico 1s 3;
    animation-play-state: paused;
}
                    

Animación básica que muestra el estado del último fotograma al terminar


#barra1 {
    animation-fill-mode: forwards;
}
                    

Animación de ida y vuelta.


    
#barra2 {
    animation-fill-mode: forwards;
    animation-direction: alternate;
}
                    

Animación con retraso en el inicio y ciclo infinito


    
#barra3 {
    animation-delay: 0.5s;
    animation-iteration-count: infinite;
    animation-direction: alternate;
}
                    

Más información

La página de MDN sobre @keyframes tiene documentación detallada sobre este componente. Son especialmente interesantes los ejemplos sobre cómo aplicar varias animaciones a un mismo elemento. También detalla los eventos de la animación disponibles para su manejo desde JavaScript. Aunque de momento no está traducida al castellano.

Esta es la ruta: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations

Y este es un ejemplo de aplicación interesante de esta propiedad, combinada con el pseudo-elemento ::target

Aquí: http://w3.unpocodetodo.info/css3/ejemplos/target-keyframes.html#articulo3