Dejar ver como cargan las imágenes de un sitio web no es lo más elegante, sobre todo si queremos dar una buena impresión con una animación o efecto. Por ello quiero enseñar rápidamente con un tutorial, o código en JavaScript, como podemos ocultar las imágenes hasta que estén todas cargadas. Básicamente existirá un elemento que ocultará la página hasta que las imágenes estén listas para ser vistas.
Pulsa Play para ver una demostración.
Existen 3 posibilidades que vamos a tratar:
- Definiendo las urls a esperar: Indicaremos las urls de las imágenes que deberemos esperar antes de ocultar el loading. Práctico si estamos usando plugins en JavaScript o solo nos interesa una imágenes concretas, como puede ser las que un usuario se puede encontrar al inicio de la página.
- Marcando con una clase las imágenes a esperar: Si las imágenes están presentes en el HTML es interesante especificar cuales son las más críticas añadiendo una clase para marcarlas.
- Automático, espera a todas las imágenes: No filtramos, esperamos a que todas las imágenes del documento sean cargadas antes de mostrar la web. Esta forma será la que más haga esperar al visitante, pero nos aseguraremos una experiencia optima sin saltos.
En todos los ejemplos tendremos un HTML con el loading que ocultará lo presente en la web.
<!-- Loading -->
<div class="loading loading--show">Cargando imágenes</div>
Con su respectivo CSS.
.loading {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: gray;
color: white;
justify-content: center;
align-items: center;
font-size: 2rem;
display: none;
}
.loading--show {
display: flex;
}
Lo puedes diseñar como creas necesario, no afectará al funcionamiento.
No obstante se conciente que la clave está en loading–show. Cuando quitemos esta clase del elemento, desaparecerá porque se aplicará un display: none
.
Por disponemos de un sencillo ejemplo que representa una web con un título y 2 imágenes. Se da por hecho que están dentro de una carpeta llamada img.
<h1>Web cargada!!!</h1>
<p><img src="img/imagen-pesada-1.jpg"></p>
<p><img src="img/imagen-pesada-2.jpg"></p>
Opción 1: Definiendo las urls a esperar
La técnica es la siguiente:
- Se crearán imágenes ocultas a partir de las rutas.
- Cada cierto tiempo, se preguntará si están cargadas.
- Cuando todas estén cargadas, se ocultará el loading (quitando la clase
loading--show
).
Habrá que crear un nuevo elemento HTML para almacenar las imágenes de precarga, por lo que añade donde quieras el siguente HTML.
<div id="preload-images"></div>
El código JavaScript sería el siguiente.
document.addEventListener('DOMContentLoaded', () => {
// Lista de urls que deseas precargar
const LIST_IMAGES_PRELOAD = ["img/imagen-pesada-1.jpg", "img/imagen-pesada-2.jpg"];
// Elemento visual del loading
const LOADING = document.querySelector('.loading');
// Obtiene elemento donde serán precargadas las imágenes
const CONTAINER_IMAGES_PRELOAD = document.querySelector('#preload-images');
// Tiempo de espera entre revisiones en ms
const SLEEP_CHECK = 50;
// Create una imagen por cada elemento de la lista LIST_IMAGES_PRELOAD y la guarda en el elemento CONTAINER_IMAGES_PRELOAD
function makePreloadImages() {
LIST_IMAGES_PRELOAD.forEach(urlImg => {
// Crea la imagen
const IMG_PRELOAD = document.createElement('img');
// Añade su ruta
IMG_PRELOAD.src = urlImg;
// Oculta para que no se muestre
IMG_PRELOAD.style = 'display: none';
// Añade al contenedor
CONTAINER_IMAGES_PRELOAD.appendChild(IMG_PRELOAD);
});
}
// Herramienta para esperar un tiempo determinado en una función asíncrona
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Comprueba de forma recursiva si todas las imágenes se han completado
// Si todas estan descargadas, quitará la clase 'loading--show' a 'loading' para ocultarlo
async function checkIfAllImagesCompleted() {
// Obtiene todas las imágenes sin completar
const NO_COMPLETES = Array.from(CONTAINER_IMAGES_PRELOAD.querySelectorAll('img')).filter((img) => {
return !img.complete;
});
if (NO_COMPLETES.length !== 0) {
// Vuelve a iterar si existe alguna sin completar
await sleep(SLEEP_CHECK);
return checkIfAllImagesCompleted();
} else {
// Oculta el loading
LOADING.classList.remove('loading--show');
}
return true;
}
// Inicia
makePreloadImages();
checkIfAllImagesCompleted();
});
Lo único que deberás modificar es la siguiente línea.
const LIST_IMAGES_PRELOAD = ["img/imagen-pesada-1.jpg", "img/imagen-pesada-2.jpg"];
Deben contener las urls de las imágenes a esperar a partir del documento HTML.
Ejemplo completo
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.loading {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: gray;
color: white;
justify-content: center;
align-items: center;
font-size: 2rem;
display: none;
}
.loading--show {
display: flex;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Lista de urls que deseas precargar
const LIST_IMAGES_PRELOAD = ["img/imagen-pesada-1.jpg", "img/imagen-pesada-2.jpg"];
// Elemento visual del loading
const LOADING = document.querySelector('.loading');
// Obtiene elemento donde serán precargadas las imágenes
const CONTAINER_IMAGES_PRELOAD = document.querySelector('#preload-images');
// Tiempo de espera entre revisiones en ms
const SLEEP_CHECK = 50;
// Create una imagen por cada elemento de la lista LIST_IMAGES_PRELOAD y la guarda en el elemento CONTAINER_IMAGES_PRELOAD
function makePreloadImages() {
LIST_IMAGES_PRELOAD.forEach(urlImg => {
// Crea la imagen
const IMG_PRELOAD = document.createElement('img');
// Añade su ruta
IMG_PRELOAD.src = urlImg;
// Oculta para que no se muestre
IMG_PRELOAD.style = 'display: none';
// Añade al contenedor
CONTAINER_IMAGES_PRELOAD.appendChild(IMG_PRELOAD);
});
}
// Herramienta para esperar un tiempo determinado en una función asíncrona
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Comprueba de forma recursiva si todas las imágenes se han completado
// Si todas estan descargadas, quitará la clase 'loading--show' a 'loading' para ocultarlo
async function checkIfAllImagesCompleted() {
// Obtiene todas las imágenes sin completar
const NO_COMPLETES = Array.from(CONTAINER_IMAGES_PRELOAD.querySelectorAll('img')).filter((img) => {
return !img.complete;
});
if (NO_COMPLETES.length !== 0) {
// Vuelve a iterar si existe alguna sin completar
await sleep(SLEEP_CHECK);
return checkIfAllImagesCompleted();
} else {
// Oculta el loading
LOADING.classList.remove('loading--show');
}
return true;
}
// Inicia
makePreloadImages();
checkIfAllImagesCompleted();
});
</script>
</head>
<body>
<!-- Loading -->
<div class="loading loading--show">Cargando imágenes</div>
<!-- Lugar donde se cargarán las imágenes de caché -->
<div id="preload-images"></div>
<h1>Web cargada!!!</h1>
<p><img src="img/imagen-pesada-1.jpg"></p>
<p><img src="img/imagen-pesada-2.jpg"></p>
</body>
</html>
Opción 2: Definiendo con una clase las imágenes a esperar
La técnica es la siguiente:
- Se espera todas las imágenes que contengan la clase
wait-loading
. - Cada cierto tiempo, se preguntará si están imágenes están cargadas.
- Cuando todas estén cargadas, se ocultará el loading (quitando la clase
loading--show
).
No olvides añadir la clase a las imágenes seleccioandas.
<img class="wait-loading" src="img/imagen-pesada-1.jpg">
<img class="wait-loading" src="img/imagen-pesada-2.jpg">
El código JavaScript sería el siguiente.
document.addEventListener('DOMContentLoaded', () => {
// Lista de urls que deseas precargar
const LIST_IMAGES_PRELOAD = Array.from(document.querySelectorAll(".wait-loading"));
// Elemento visual del loading
const LOADING = document.querySelector('.loading');
// Tiempo de espera entre revisiones en ms
const SLEEP_CHECK = 50;
// Herramienta para esperar un tiempo determinado en una función asíncrona
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Comprueba de forma recursiva si todas las imágenes se han completado
// Si todas estan descargadas, quitará la clase 'loading--show' a 'loading' para ocultarlo
async function checkIfAllImagesCompleted() {
// Obtiene todas las imágenes sin completar
const NO_COMPLETES = LIST_IMAGES_PRELOAD.filter((img) => {
return !img.complete;
});
if (NO_COMPLETES.length !== 0) {
// Vuelve a iterar si existe alguna sin completar
await sleep(SLEEP_CHECK);
return checkIfAllImagesCompleted();
} else {
// Oculta el loading
LOADING.classList.remove('loading--show');
}
return true;
}
// Inicia
checkIfAllImagesCompleted();
});
Ejemplo completo
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.loading {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: gray;
color: white;
justify-content: center;
align-items: center;
font-size: 2rem;
display: none;
}
.loading--show {
display: flex;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Lista de urls que deseas precargar
const LIST_IMAGES_PRELOAD = Array.from(document.querySelectorAll(".wait-loading"));
// Elemento visual del loading
const LOADING = document.querySelector('.loading');
// Tiempo de espera entre revisiones en ms
const SLEEP_CHECK = 50;
// Herramienta para esperar un tiempo determinado en una función asíncrona
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Comprueba de forma recursiva si todas las imágenes se han completado
// Si todas estan descargadas, quitará la clase 'loading--show' a 'loading' para ocultarlo
async function checkIfAllImagesCompleted() {
// Obtiene todas las imágenes sin completar
const NO_COMPLETES = LIST_IMAGES_PRELOAD.filter((img) => {
return !img.complete;
});
if (NO_COMPLETES.length !== 0) {
// Vuelve a iterar si existe alguna sin completar
await sleep(SLEEP_CHECK);
return checkIfAllImagesCompleted();
} else {
// Oculta el loading
LOADING.classList.remove('loading--show');
}
return true;
}
// Inicia
checkIfAllImagesCompleted();
});
</script>
</head>
<body>
<!-- Loading -->
<div class="loading loading--show">Cargando imágenes</div>
<!--Contenido -->
<h1>Web cargada!!!</h1>
<p><img class="wait-loading" src="img/imagen-pesada-1.jpg"></p>
<p><img class="wait-loading" src="img/imagen-pesada-2.jpg"></p>
</body>
</html>
Opción 3: Automático, espera a todas las imágenes
La técnica es la siguiente:
- Se capturan todas las imágenes presentes en el documento.
- Cada cierto tiempo, se preguntará si están imágenes están cargadas.
- Cuando todas estén cargadas, se ocultará el loading (quitando la clase
loading--show
).
El código JavaScript sería el siguiente.
document.addEventListener('DOMContentLoaded', () => {
// Lista de urls que deseas precargar
const LIST_IMAGES_PRELOAD = Array.from(document.images);
// Elemento visual del loading
const LOADING = document.querySelector('.loading');
// Tiempo de espera entre revisiones en ms
const SLEEP_CHECK = 50;
// Herramienta para esperar un tiempo determinado en una función asíncrona
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Comprueba de forma recursiva si todas las imágenes se han completado
// Si todas estan descargadas, quitará la clase 'loading--show' a 'loading' para ocultarlo
async function checkIfAllImagesCompleted() {
// Obtiene todas las imágenes sin completar
const NO_COMPLETES = LIST_IMAGES_PRELOAD.filter((img) => {
return !img.complete;
});
if (NO_COMPLETES.length !== 0) {
// Vuelve a iterar si existe alguna sin completar
await sleep(SLEEP_CHECK);
return checkIfAllImagesCompleted();
} else {
// Oculta el loading
LOADING.classList.remove('loading--show');
}
return true;
}
// Inicia
checkIfAllImagesCompleted();
});
Ejemplo completo
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.loading {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: gray;
color: white;
justify-content: center;
align-items: center;
font-size: 2rem;
display: none;
}
.loading--show {
display: flex;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Lista de urls que deseas precargar
const LIST_IMAGES_PRELOAD = Array.from(document.images);
// Elemento visual del loading
const LOADING = document.querySelector('.loading');
// Tiempo de espera entre revisiones en ms
const SLEEP_CHECK = 50;
// Herramienta para esperar un tiempo determinado en una función asíncrona
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Comprueba de forma recursiva si todas las imágenes se han completado
// Si todas estan descargadas, quitará la clase 'loading--show' a 'loading' para ocultarlo
async function checkIfAllImagesCompleted() {
// Obtiene todas las imágenes sin completar
const NO_COMPLETES = LIST_IMAGES_PRELOAD.filter((img) => {
return !img.complete;
});
if (NO_COMPLETES.length !== 0) {
// Vuelve a iterar si existe alguna sin completar
await sleep(SLEEP_CHECK);
return checkIfAllImagesCompleted();
} else {
// Oculta el loading
LOADING.classList.remove('loading--show');
}
return true;
}
// Inicia
checkIfAllImagesCompleted();
});
</script>
</head>
<body>
<!-- Loading -->
<div class="loading loading--show">Cargando imágenes</div>
<!--Contenido -->
<h1>Web cargada!!!</h1>
<p><img src="img/imagen-pesada-1.jpg"></p>
<p><img src="img/imagen-pesada-2.jpg"></p>
</body>
</html>
{{ comments.length }} comentarios