Cómo codear un sitio con scroll de un alien aterrizando
Spanish (Español) translation by Jorge Montoya (you can also view the original English article)
En este tutorial, el segundo de una serie de dos, vamos a tomar la maravillosa ilustración vectorial realizada en "Cómo crear un fondo largo para un sitio" de Yulia Sokolova, y codearlo en un sitio real.
Qué es lo que vamos a construir
Vamos a juntar las cosas de tal manera que a medida que te desplaces desde arriba hacia abajo, vas a ver un Alien en su camino a aterrizar. Al principio vamos a ver a un OVNI flotando en el espacio.



A medida que nos desplazamos hacia abajo, el OVNI va a alcanzar la atmósfera y convertirse en un cometa alien.



Y, finalmente, cuando atraviesa la línea de árboles, se va a a transformar en un "hombrecito verde" que se posa sobre la tierra.



¡Mirá la demostración!
Imágenes SVG
En este proyecto vamos a utilizar imágenes SVG de tal manera que podamos aprovechar su capacidad de redimensionarse con fluidez y su pequeño tamaño de archivo.
Antes de empezar a codificar, necesitará la imagen creada en la primera parte de esta serie de tutoriales, dividida en cuatro archivos SVG:
- El OVNI como un archivo llamado "ufo.svg"
- El "cometa alienígena" como un archivo llamado "alien_comet.svg"
- El "pequeño hombre verde" como un archivo llamado "alien_landing.svg"
- La imagen de fondo sin los tres elementos anteriores como un archivo denominado "background.svg"
Usted puede exportar estas imágenes SVG desde su aplicación gráfica preferida si lo desea o alternativamente, encontrará las cuatro imágenes listas para su uso en los archivos de origen de GitHub.
Configure la Estructura Básica
Cree una nueva carpeta para su proyecto y dentro de ella cree una subcarpeta llamada "css" y otra llamada "images".
Copie y pegue sus cuatro imágenes SVG en la nueva carpeta "images".
En la carpeta "css" cree un archivo denominado "style.css".
En la carpeta principal, cree un nuevo archivo denominado "index.html".
Su estructura de carpetas debería verse así:



En el archivo "index.html" agregue el siguiente HTML básico para obtener los elementos esenciales y cargue la hoja de estilo:
1 |
<!DOCTYPE html>
|
2 |
<html lang="en"> |
3 |
<head>
|
4 |
<meta charset="UTF-8"> |
5 |
<title>Scrolling Alien Lander</title> |
6 |
<link rel="stylesheet" href="css/coding_style.css"> |
7 |
</head>
|
8 |
<body>
|
9 |
|
10 |
|
11 |
|
12 |
</body>
|
13 |
</html>
|
Adicione el Fondo
Podría parecer contra-intuitivo, pero en realidad vamos a añadir nuestra imagen de fondo utilizando un elemento img en lugar de una imagen de fondo CSS. Estamos haciendo esto porque:
- Queremos aprovechar la capacidad de SVG para redimensionarse, llenando toda la ventana de visualización con nuestra imagen "background.svg" sin importar cuáles son las dimensiones de la ventana del navegador.
- Para que la técnica de desplazamiento funcione, necesitamos conocer la altura de la imagen de fondo.
- Debido a que estamos permitiendo que nuestra imagen de fondo sea de tamaño fluido no tenemos forma de saber cuál será su altura de antemano.
- Como no podemos conocer la altura de la imagen de fondo de antemano, tendremos que detectarla después de la imagen después de que se ha cargado.
- Si configuramos "background.svg" como una imagen de fondo CSS, su altura no afectaría al diseño del sitio, por lo que su altura será difícil de detectar.
- Al insertar "background.svg" como una imagen normal, su altura tendrá efecto sobre el diseño del sitio, haciendo que su altura sea relativamente fácil de detectar usando jQuery.
Ahora que usted entiende por qué estamos tomando este enfoque, ¡vamos a empezar a codificar!
En su archivo "index.html" adicione este código:
1 |
<img class="background" src="images/background.svg"> |
Si previsualiza su archivo en un navegador ahora debe ver la imagen llenando la ventana de visualización. Sin embargo, todavía habrá algún espacio en blanco alrededor de los bordes.
Esto se debe a que los navegadores incluyen un pequeño margen en el elemento body por defecto. Para sobreescribir esto, en el archivo "style.css" agregue este CSS:
1 |
body { |
2 |
margin: 0; |
3 |
}
|
También hay otro css predeterminado del navegador que debemos sobreescribir, el de la propiedad display en las imágenes establecido como inline. Si se desplaza hasta la parte inferior de la página, verá que hay un pequeño espacio en blanco debajo de la imagen debido a este valor predeterminado. Cámbielo al agregar:
1 |
img { |
2 |
display: block; |
3 |
}
|
Ahora debería ver la imagen "background.svg" llenando la ventana hasta el ras de los bordes y si redimensiona el ancho de la ventana verá que la imagen SVG también se redimensiona para adaptarse al nuevo tamaño. La altura del diseño del sitio también cambiará para mantener la relación de aspecto correcta para la imagen "background.svg".
Agregue un Contenedor de Primer Plano
Para hacer que la imagen que acabamos de colocar se comporte como una imagen de fondo, necesitamos una manera de hacer que el resto de nuestro contenido se sitúe encima de esta en primer plano. Podemos lograr esto añadiendo un elemento div que actuará como un contenedor, luego modificando las propiedades position y z-index.
En su archivo "index.html" después de la imagen que acaba de agregar, inserte este nuevo div:
1 |
<div class="foreground"> |
2 |
</div>
|
Y en "style.css" añada este CSS:
1 |
.foreground { |
2 |
position: absolute; |
3 |
top: 0; |
4 |
left: 0; |
5 |
height: 100%; |
6 |
width: 100%; |
7 |
z-index: 1; |
8 |
}
|
Revisemos lo que estamos haciendo con el código arriba.
Primero, al establecer position a absolute sacamos el elemento del flujo regular del documento (lo que de otro modo lo situaría debajo de la imagen de fondo), permitiéndonos ubicarlo en cualquier lugar que elijamos.
Luego establecemos las propiedades top y left a 0, lo que desplaza el elemento hasta la parte superior de la ventana y lo alinean horizontalmente con nuestra imagen de fondo.
Después de eso le damos al elemento un height y width del 100%. Esto asegura que el elemento no se colapse a cero, ocultando cualquier contenido dentro de él.
Por último establecemos z-index a 1, lo que trae el elemento hacia adelante para que se sitúe delante de nuestra imagen de fondo (que está en un z-index predeterminado de auto). Esto evita que el contenido dentro del elemento sea ocultado por la imagen de fondo.
Nuestro contenedor de primer plano ahora está listo para que se le agregue contenido.
Agregue el Panel del OVNI
La forma en que vamos a hacer que nuestro OVNI "aterrice" en el suelo en la parte inferior es mediante la creación de tres paneles, uno para cada etapa del "aterrizaje". Iremos agregando la imagen SVG correspondiente para cada panel, como el archivo "ufo.svg" por ejemplo, como una imagen de fondo de posición fija. La imagen permanecerá en su lugar durante el desplazamiento mientras el fondo se mueve detrás de ella, creando así la ilusión de descenso.
Dentro de su div de "primer plano", agregue este nuevo div:
1 |
<div class="ufo_section"></div> |
Ahora adicione el siguiente código a su CSS:
1 |
.ufo_section { |
2 |
height: 100%; |
3 |
background: url(../images/ufo.svg); |
4 |
background-repeat: no-repeat; |
5 |
background-position: center; |
6 |
background-size: 40% auto; |
7 |
background-attachment: fixed; |
8 |
}
|
En la primera línea de nuestro código arriba le estamos dando al elemento una height de 100% para asegurar que su contenido será visible. A continuación, agregaremos nuestra imagen "ufo.svg" como el fondo. Estamos configurando background-repeat a no-repeat, ya que sólo queremos que aparezca un OVNI, y luego estamos haciendo que background-position ubique la imagen en el centro tanto horizontal y verticalmente.
Con nuestra propiedad background-size, estamos estableciendo el ancho como un valor basado en porcentajes y permitiendo que la altura se calcule automáticamente. Este ancho se extrae de la imagen vectorial original en la que el ancho del OVNI es aproximadamente el 40% del ancho de la ilustración general.
Al configurar el ancho de nuestra imagen "ufo.svg" como un porcentaje, cuando la ventana se redimensiona y la imagen "background.svg" cambia con ella, la imagen de OVNI también ajustará su ancho para mantener las proporciones deseadas.
En la línea final, establecemos background-attachment a fixed, lo que significa que la imagen permanecerá fija en su lugar a medida que nos desplazamos, dándonos nuestra ilusión de descenso.
Trate de refrescar su página y desplazarse ahora - usted debe ver el OVNI moviéndose verticalmente entre los planetas.
Agregue el Cometa y los Paneles de Aterrizaje
A medida que se desplaza hacia abajo en su sitio, una vez que vaya hacia abajo lo suficientemente lejos se darás cuenta de que el OVNI desaparece. Esto sucede porque nos estamos desplazando más allá de la altura del panel ufo_section, por lo que ya no podemos ver su fondo.
Vamos a apilar tres paneles como este uno encima del otro, de modo que cuando terminemos de desplazarnos por uno y su fondo desaparece el fondo del panel siguiente aparece, creando el efecto de una imagen que se sustituye por la siguiente.
Así que ahora vamos a repetir el proceso que utilizamos arriba para insertar las imágenes "alien_comet.svg" y "alien_landing.svg" .
A su HTML, añada lo siguiente justo después de su div ufo_section y aún dentro de su div de primer plano:
1 |
<div class="comet_section"></div> |
2 |
<div class="landing_section"></div> |
Luego añada estas nuevas clases a su CSS:
1 |
.comet_section { |
2 |
height: 100%; |
3 |
background: url(../images/alien_comet.svg); |
4 |
background-repeat: no-repeat; |
5 |
background-position: center; |
6 |
background-size: 15% auto; |
7 |
background-attachment: fixed; |
8 |
}
|
9 |
|
10 |
.landing_section { |
11 |
height: 100%; |
12 |
background: url(../images/alien_landing.svg); |
13 |
background-repeat: no-repeat; |
14 |
background-position: center; |
15 |
background-size: 15% auto; |
16 |
background-attachment: fixed; |
17 |
position: relative; |
18 |
}
|
Estamos usando todo el mismo código y técnicas aquí, con sólo los nombres de archivo de imagen cambiados y el ancho de la propiedad background-size establecido en 15% para adaptarse a las imágenes más angostas que acabamos de agregar.
Su CSS Completo
Su archivo "style.css" ya está terminado y debería contener el código siguiente:
1 |
body { |
2 |
margin: 0; |
3 |
}
|
4 |
|
5 |
img { |
6 |
display: block; |
7 |
}
|
8 |
|
9 |
.foreground { |
10 |
position: absolute; |
11 |
top: 0; |
12 |
left: 0; |
13 |
height: 100%; |
14 |
width: 100%; |
15 |
z-index: 1; |
16 |
}
|
17 |
|
18 |
.ufo_section { |
19 |
height: 100%; |
20 |
background: url(../images/ufo.svg); |
21 |
background-repeat: no-repeat; |
22 |
background-position: center; |
23 |
background-size: 40% auto; |
24 |
background-attachment: fixed; |
25 |
}
|
26 |
|
27 |
.comet_section { |
28 |
height: 100%; |
29 |
background: url(../images/alien_comet.svg); |
30 |
background-repeat: no-repeat; |
31 |
background-position: center; |
32 |
background-size: 15% auto; |
33 |
background-attachment: fixed; |
34 |
}
|
35 |
|
36 |
.landing_section { |
37 |
height: 100%; |
38 |
background: url(../images/alien_landing.svg); |
39 |
background-repeat: no-repeat; |
40 |
background-position: center; |
41 |
background-size: 15% auto; |
42 |
background-attachment: fixed; |
43 |
position: relative; |
44 |
}
|
Vuelva a su sitio ahora, desplácese hacia abajo y debería ver que el OVNI se convierte en el cometa, y un poco más abajo se convierte en el "pequeño hombre verde".
Añada Cálculos de Altura para el Panel
Ahora mismo usted se dará cuenta de que tenemos un par de problemas que resolver al desplazarnos, los cuales son:
- Cada uno de los tres paneles no es lo suficientemente alto. Esto hace que parezca que el módulo de aterrizaje extraterrestre cambia de una forma a otra demasiado pronto, por lo que nunca llega al suelo.
- Puede ver la imagen "alien_comet.svg" empezar a emerger antes de que la imagen de "ufo.svg" haya desaparecido por completo, lo cual se ve raro.
Debido a que nuestra imagen "background.svg" no tiene un tamaño fijo, no conoceremos la altura exacta en píxeles que debe tener cada panel antes de cargarlo. Sin embargo, lo que podemos decidir por adelantado es la altura que cada panel debería tener como un porcentaje de la altura de "background.svg".
Utilizando jQuery podemos implementar este proceso:
- Defina la altura que queremos que cada panel tenga como un porcentaje (o fracción) de la altura de la imagen "background.svg".
- Detecte la altura de "background.svg" después de que cargue.
- Calcule y establezca las alturas de los paneles en base a las dos piezas de información anteriores.
Mientras estamos en ello, también agregaremos un par de divs vacíos adicionales para actuar como espaciadores entre cada panel y estableceremos su altura usando jQuery también. Agregar espacio entre los paneles hará que la transición sea más suave, resolviendo el problema de ver la imagen "alien_comet.svg" antes de que desaparezca la imagen "ufo.svg".
Actualice su HTML de tal manera que haya un div separador entre cada div existente así:
1 |
<div class="foreground"> |
2 |
<div class="ufo_section"></div> |
3 |
<div class="spacer_one"></div> |
4 |
<div class="comet_section"></div> |
5 |
<div class="spacer_two"></div> |
6 |
<div class="landing_section"></div> |
7 |
</div>
|
Y en la sección head, cargue jQuery añadiendo lo siguiente:
1 |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script> |
Configuración de la Función JavaScript
Antes de la etiqueta de </body> de cierre, cree un par de etiquetas <script></script> y configure una nueva función dentro de ellas así: y configure una nueva función dentro del mismo modo:
1 |
<script>
|
2 |
|
3 |
function set_section_heights(){ |
4 |
|
5 |
}
|
6 |
|
7 |
</script>
|
Queremos que esta función se active cuando la página se cargue por primera vez, y en cualquier momento que se redimensione, así que para lograr esto, agregue el siguiente código después de la etiqueta script de apertura:
1 |
$(document).ready(function(){ |
2 |
set_section_heights(); |
3 |
});
|
4 |
|
5 |
$(window).resize(function(){ |
6 |
set_section_heights(); |
7 |
});
|
Obtenga la Altura de la Imagen de Fondo
Dentro de la función set_section_heights(), lo primero que debemos hacer es averiguar qué altura tiene nuestra imagen de fondo actualmente y guardarla como variable. Para ello, agregue este código:
1 |
var doc_height = $(".background").height(); |
Con la primera parte del código, $(". background"), jQuery encuentra el elemento con el nombre de clase background. La función .height() agregada obtiene la altura en píxeles de ese elemento como un entero. Esto nos indica qué tan alta es nuestra imagen "background.svg" y guarda ese número en la variable doc_height.
Defina Alturas de Sección Previstas
Ahora vamos a configurar un objeto en el que podemos definir:
- El nombre de clase de cada elemento para el que queremos establecer una altura.
- Qué tan alto debe ser ese elemento como una fracción de la altura del fondo.
Vamos a iterar a través de este objeto y utilizar los valores que contiene para cambiar el tamaño de las secciones en nuestro primer plano.
Comencemos con sólo una entrada en el objeto:
1 |
var section_heights = { |
2 |
"ufo_section": 0.25 |
3 |
}
|
Aquí hemos establecido el índice, (el valor de la izquierda), a ufo_section para que coincida con el nombre de la clase de nuestra primera sección.
Luego hemos establecido el valor a 0.25 que es otra manera de expresar 25%. En un momento, vamos a multiplicar este valor por el número almacenado en la variable doc_height, es decir la altura de la imagen de fondo. Al hacer esto estaremos diciendo que queremos que el panel ufo_section sea el 25% de la altura actual de "background.svg".
Por ejemplo, si la altura de "background.svg" fuera 1000px, la altura de ufo_section aparecería como 250px:
1000 * 0.25 = 250
Ahora que hemos analizado cómo funcionará este objeto, vamos a añadir algunas entradas para los otros elementos en los que queremos establecer alturas. Actualice su objeto a lo siguiente:
1 |
var section_heights = { |
2 |
"ufo_section": 0.25, |
3 |
"spacer_one": 0.03, |
4 |
"comet_section": 0.36, |
5 |
"spacer_two": 0.06, |
6 |
"landing_section": 0.298 |
7 |
}
|
Nota: He seleccionado estos valores basado en prueba y error, así que siéntase libre de jugar con los números después de completar este tutorial para ver los efectos.
Iterar el Objeto section_heights
Con nuestro objeto completo estamos listos para comenzar a iterar a través de él y redimensionar nuestros paneles.
Primero necesitaremos una función $.each() para iterar el objeto section_heights y extraer el índice y el valor (representando el nombre de la clase y la altura respectivamente), de cada entrada que contenga.
Agregue este código después de su objeto section_heights:
1 |
$.each( section_heights, function( index, value ) { |
2 |
console.log( "Index: " + index, "| Value: " + value ); |
3 |
});
|
Para permitirle ver cómo la función de iteración anterior genera las variables de index y value, estamos usando console.log() para escribir un pequeño mensaje en la consola para cada entrada del objeto section_heights.
Recargue su sitio, abra Chrome Web Developer Tools (o su equivalente en su navegador preferido) y mire la consola. Usted debe ver esto:



A la izquierda de cada mensaje después de Índice: usted puede ver el index para cada entrada, es decir, los nombres de clase de los elementos que queremos redimensionar.
A la derecha de cada mensaje después de Valor: puede ver el value para cada entrada, es decir la fracción de la altura total que debe tener cada panel.
Calcular y Establecer Alturas de Sección
Ahora en vez de simplemente registrar estos datos en la consola, vamos a usarlos para establecer los tamaños de nuestras secciones de primer plano. Elimine la línea console.log() y cámbiela por la siguiente:
1 |
$( "." + index ).height( Math.floor(value * doc_height) ); |
Vamos a analizar lo que esta línea hace.
Primero tenemos $("." + index). Usamos esto para encontrar el elemento que queremos redimensionar. Por ejemplo, con la primera entrada en nuestro objeto el index está establecido a ufo_section. En este caso, la primera parte de nuestro código se evaluará para convertirse en $.(".ufo_section"). Con este código, se solicita a jQuery que busque en la página el elemento con la clase ufo_section.
A continuación añadimos .height (...). Con este código, jQuery establecerá la altura del elemento que ha encontrado, cambiándolo al valor pasado entre los corchetes.
Entre los corchetes verá value * doc_height. Aquí es donde estamos haciendo la multiplicación que mencionamos antes para calcular la altura del panel deseada. Por ejemplo, la primera entrada de nuestro objeto tiene el valor 0.25. Este número se multiplicará por el número guardado en la variable doc_height.
Alrededor de la multiplicación de esas dos variables usted verá Math.floor(). Esto redondea el resultado de nuestra multiplicación hasta el número entero más cercano.
Así que poniendo todo junto, si el valor de doc_height es 5197, la primera entrada en nuestro objeto se multiplicaría por 0.25 dando un resultado de 1299.25.
Math.floor() redondeará esa cantidad a 1299. Esto significa que nuestro código ahora se evaluará para convertirse en: $.(".ufo_section").height (1299);
Con esta línea, jQuery encontrará el elemento con la clase ufo_section y establecerá su altura en 1299px.
Su HTML y JavaScript Completos
Eso completa su HTML y JavaScript. Su archivo completo "index.html" debería contener ahora este código:
1 |
<!DOCTYPE html>
|
2 |
<html lang="en"> |
3 |
<head>
|
4 |
<meta charset="UTF-8"> |
5 |
<title>Scrolling Alien Lander</title> |
6 |
<link rel="stylesheet" href="css/coding_style.css"> |
7 |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script> |
8 |
</head>
|
9 |
<body>
|
10 |
|
11 |
<img class="background" src="images/background.svg"> |
12 |
|
13 |
<div class="foreground"> |
14 |
<div class="ufo_section"></div> |
15 |
<div class="spacer_one"></div> |
16 |
<div class="comet_section"></div> |
17 |
<div class="spacer_two"></div> |
18 |
<div class="landing_section"></div> |
19 |
</div>
|
20 |
|
21 |
<script>
|
22 |
|
23 |
$(document).ready(function(){ |
24 |
set_section_heights(); |
25 |
});
|
26 |
|
27 |
$(window).resize(function(){ |
28 |
set_section_heights(); |
29 |
});
|
30 |
|
31 |
function set_section_heights(){ |
32 |
|
33 |
var doc_height = $(".background").height(); |
34 |
|
35 |
var section_heights = { |
36 |
"ufo_section": 0.25, |
37 |
"spacer_one": 0.03, |
38 |
"comet_section": 0.36, |
39 |
"spacer_two": 0.06, |
40 |
"landing_section": 0.298 |
41 |
}
|
42 |
|
43 |
$.each( section_heights, function( index, value ) { |
44 |
$( "." + index ).height( Math.floor(value * doc_height) ); |
45 |
});
|
46 |
|
47 |
}
|
48 |
|
49 |
</script>
|
50 |
|
51 |
</body>
|
52 |
</html>
|
Recargue su sitio ahora para ver el código en acción y cuando inspeccione su HTML debería ver los tamaños recién calculados aparecer en línea:



Redimensione la ventana del navegador y verá que estos valores se vuelven a calcular y se actualizan, por ejemplo:



¡Y Usted Está Listo!
¡Eche un vistazo al resultado final! Ahora, cuando empiece en la parte superior de la página y comience a desplazarse, verá que el OVNI comienza a descender. Cuando llega a la atmósfera desaparece por un momento y un "cometa alienígena" toma su lugar y continúa el descenso. En la parte superior de los árboles desaparece una vez más y un "pequeño hombre verde" completa el viaje hasta el suelo.



Como mencioné anteriormente, es una gran idea jugar con los valores establecidos en el objeto section_heights para que pueda ver cómo afectan el flujo del aterrizaje a través de sus varias etapas.
Espero que haya disfrutado de este tutorial y que tienga algunas ideas nuevas para cosas geniales que puede hacer con imágenes SVG y fondos fijos.
Gracias de nuevo a Yulia por la ilustración vectorial original, gracias a usted por leer, y ¡lo veré de nuevo pronto!





