El siempre genial David Walsh publicaba el otro día un pequeño artículo sobre fondos animados con CSS3. En los comentarios, alguien sugería mejorarlo añadiendo un efecto parallax, así que me he animado a hacerlo.

¿Qué vamos a conseguir? Una bucólica escena campestre, en la que las nubes pasan mientras el Sol sale y se pone. Todo esto con sólo un div y un span. Las nubes podrían haber sido generadas también con CSS, pero me parecía demasiado lío y opté en su lugar por usar 3 imágenes. Podéis ver el resultado en estas páginas de demo:

La versión sin prefijos funciona (actualmente, según caniuse.com) en Firefox e IE10. En Chrome es necesaria la versión con prefijos.

Por comodidad, durante el resto del tutorial pondré el código SIN prefijos. En ambas demos el código CSS está en la cabecera del propio archivo, por lo que puedes copiar el código que necesites simplemente dándole a ver código fuente.

Veamos cómo se consigue este efecto.

Preparando la escena con degradados CSS3

El código HTML no podría ser más simple: un div con un span dentro.

<div id="container">
    <span id="clouds"></span>
</div>

Con CSS damos un tamaño al contenedor, lo centramos en la pantalla y le ponemos un degradado para hacer el cielo:

#container {
    width: 600px;
    height: 600px;
    margin: -300px;
    background: linear-gradient(#3D6CC4, #2587EF, #D1741D 80%,  #EC331C);
    background-size:
    1200px 1200px;
    position: absolute;
    overflow: hidden;
    top: 50%;
    left: 50%;
}

Es importante la regla background-size (nueva en CSS3), que permite definir el tamaño que ocupa un fondo, independientemente del elemento al que se aplique. Si te fijas en el degradado, verás que acaba siendo rojo. Con background-size damos un tamaño al degradado del doble de su contenedor, lo que oculta la parte roja y nos permitirá luego simular un amanecer/atardecer.

Degradado con CSS3

Este es el degradado que usamos, sin ocultar nada.

En este punto tendremos simplemente un rectángulo azul, lo que es un poco aburrido. Vamos a añadir el Sol y la tierra mediante pseudoelementos generados con CSS:

#container:after {
    width: 100px;
    height: 100px;
    border-radius: 50px;
    background: linear-gradient(#EBE612, #E9B519, #E5142C);
    background-size: 200px 200px; /*El doble del alto para poder moverlo*/
    position: absolute;
    top: 60%;
    left: 50%;
    margin-left: -50px;
}

Al igual que con el cielo, el degradado del Sol es el doble de grande que el propio elemento, para poder animarlo después.

#container:before {
    height: 250px;
    width: 100%;
    background: linear-gradient(#1C6529, #00B337);
    position: absolute;
    bottom: 0;
    left: 0;
    z-index: 10;
}

Estos dos pseudoelementos (y las nubes, después) comparten una regla que agrupamos aquí:

#container:after,
#container:before,
#clouds:after,
#clouds:before {
    content: "";
}

Con esto tenemos el cielo, la tierra y el Sol… aunque donde no debe. ¿O sí? Su posición tiene que ser esa, ya que es el centro del movimiento circular que crearemos después con una animación.

Sol generado con CSS3

El Sol se coloca en el centro de la circunferencia que luego seguirá.

Lo que sí hay que hacer es ocultarlo y, para ello, actualizamos el código añadiendo la propiedad z-index:

#container:after {
    width: 100px;
    height: 100px;
    border-radius: 50px;
    background: linear-gradient(#EBE612, #E9B519, #E5142C);
    background-size: 200px 200px; /*El doble del alto para poder moverlo*/
    position: absolute;
    top: 60%;
    left: 50%;
    margin-left: -50px;
    z-index: 1;
}
#container:before {
    height: 250px;
    width: 100%;
    background: linear-gradient(#1C6529, #00B337);
    position: absolute;
    bottom: 0;
    left: 0;
    z-index: 10;
}

Animando el fondo con animation keyframes

Ya tenemos una base, así que ya podemos empezar con lo bueno. Vamos a animar el Sol, haciendo que salga y se ponga. Para ello usaremos las animaciones de CSS3, cuya sintaxis se resume en:

@keyframes nombreDeLaAnimacion {
    0% {
        propiedad: valorinicial;
    }
    50% {
        propiedad: valorintermedio;
    }
    100% {
        propiedad: valorfinal;
    }
}

Los estados intermedios pueden ser los que se quiera. Además, 0% y 100% pueden sustituirse por las palabras clave from y to. Esto es, de hecho, lo que hacemos en nuestro caso:

@keyframes animatedBg1 {
    from {
        background-position: 0 -600px;
    }
    to {
        background-position: 0 0;
    }
}

La primera animación, la del cielo, es muy simple: creamos una animación que mueva el fondo 600px de forma vertical. ¿Por qué usamos esta forma y no animamos el degradado en sí mismo? Porque, al menos por ahora, no se puede.

La forma de animar degradados que tenemos es crear un degradado más grande que su contenedor y animar su posición. Es un poco más engorroso, pero funciona.

Nuestra animación empieza con el fondo ya desplazado (para que empiece en la parte roja, del amanecer) y se desplaza hasta la parte de arriba (el cielo azul). ¿Y cómo vuelve a la parte roja para el anochecer? Pues podríamos establecer otro punto más, con el código así:

@keyframes animatedBg1 {
    0% {
        background-position: 0 -600px;
    }
    50% {
        background-position: 0 0;
    }
    100% {
        background-position: 0 -600px;
    }
}

Pero realmente no nos hace falta, ya que podemos simplemente ejecutar la animación inicial, del revés.

Las animaciones CSS se definen, con el código de @keyframes que hemos puesto hasta ahora, y se aplican a el (o los) elemento(s) que queramos con este código:

#elemento {
    animation: nombreDeAnimacion duracionEnSegundos;
}

Hay muchas opciones (que se pueden consultar en el W3C), entre las que se encuentra la dirección de la animación: podemos establecer si la animación se ejecuta de 0% a 100% (normal, por defecto), de 100% a 0% (reverse), alternativamente en una dirección u otra (alternate) o alternativamente pero empezando de 100% a 0% (alternate-reverse).

En nuestro caso, usamos alternate para que la animación vuelva hacia atrás y, hacemos que dure 5s, la mitad de lo que durará la escena total:

#container {
    width: 600px;
    height: 600px;
    margin: -300px;
    background: linear-gradient(#3D6CC4, #2587EF, #D1741D 80%,  #EC331C);
    background-size: 1200px 1200px;
    animation: animatedBg1 5s alternate infinite;
    position: absolute;
    overflow: hidden;
    top: 50%;
    left: 50%;
}

La animación del Sol es un poco más complicada: vamos a animar el degradado (al igual que con el cielo) para hacerlo más rojizo en el amanecer y anochecer, agrandarlo en dichos puntos, y hacer que siga una circunferencia (o, más bien, media circunferencia).

@keyframes rotateSun {
    0%{
        transform: rotate(180deg)
            translate(-300px)
            rotate(-180deg)
            scale(1.2)
        ;
        background-position: 0 -100px;
    }
    50%{
         transform: rotate(90deg)
             translate(-300px)
             rotate(-90deg)
             scale(1)
        ;
    background-position: 0 0;
    }
    100%{
        transform: rotate(0deg)
            translate(-300px)
            rotate(0deg)
            scale(1.2)
        ;
        background-position: 0 -100px;
    }
}

¿Por qué hay dos rotate en la transformación? Para evitar que el degradado gire con el Sol y conseguir que se mantenga en todo momento vertical. Esta técnica tengo que agradecérsela a Lea Verou.

Ahora aplicamos esta animación al Sol:

#container:after {
    width: 100px;
    height: 100px;
    border-radius: 50px;
    background: linear-gradient(#EBE612, #E9B519, #E5142C);
    background-size: 200px 200px; /*El doble del alto para poder moverlo*/
    position: absolute;
    top: 60%;
    left: 50%;
    margin-left: -50px;
    z-index: 1;
    animation: rotateSun 10s linear infinite;
}

Ya tenemos un Sol girando y el cielo cambiando de color según su posición, como podéis ver en esta demo:

http://demo.cmorales.es/background-animation/no-clouds.html

Es el momento de añadir las nubes…

Fondo animado con efecto parallax

Esta era la sugerencia que le hacían a David Walsh en los comentarios y, visto todo el código anterior, puede que me dispersara un poco a la hora de aplicarlo 😀

El efecto parallax (o paralaje, en castellano) se consigue moviendo a diferentes velocidades los elementos de un plano: cuanto más cerca del “espectador” estén, más rápido se desplazan. Con esto se consigue una apariencia pseudo3D bastante resultona.

Lo primero que tenemos que hacer es situar las nubes en el escenario, y para ello vamos a usar el span que creamos en el HTML:

#clouds {
    background: url(img/clouds_1.png) repeat-x 0 0;
    top: 10%;
    z-index: 18;
}

#clouds:before {
    background: url(img/clouds_2.png) repeat-x 0 0;
    top: 1%;
    z-index: 19;
}

#clouds:after {
    background: url(img/clouds_3.png) repeat-x 0 0;
    top: 7%;
    z-index: 20;
}

#clouds,
#clouds:before,
#clouds:after {
    width: 100%;
    height: 100%;
    position: absolute;
}

Colocamos las 3 imágenes de nubes a distinta altura (top) y con distintos z-index (mayores que el Sol para que éste pase por detrás).

Nubes situadas en la escena previa a la animación

Las nubes, situadas a alturas diferentes.

Ahora, definimos una sola animación:

@keyframes animatedBg2 {
from {
background-position: 0 0;
}
to {
background-position: -640px 0;
}

Esta animación, básicamente, mueve el fondo 640px hacia la izquierda. Dado que las imágenes miden precisamente esos 640px y que hemos puesto background repeat-x, al finalizar la animación el fondo estará como al principio y no se notará salto.

Ahora sólo tenemos que aplicar la animación a cada nube, con una velocidad diferente para cada una:

#clouds {
    animation: animatedBg2 16s linear infinite;
}

#clouds:before {
    animation: animatedBg2 13s linear infinite;
}

#clouds:after {
    animation: animatedBg2 10s linear infinite;
}

¡Listo! Ya tenemos una escena con unas bonitas animaciones. ¿Cuántos archivos de Flash o líneas de JavaScript hemos necesitado? CERO.

One thought on “Fondo animado con CSS3

Deja un comentario

Facebook