Contenido del curso
Optimización de imágenes
Paginación
Almacenamiento local
Bonus
Próximos pasos
Fallback de imágenes con evento error en JS
Resumen
Cuando una API devuelve pósters rotos o vacíos, tu interfaz queda con huecos blancos y el atributo alt como única pista. La solución pasa por detectar el evento error de la imagen en JavaScript y reemplazar el src por una imagen de fallback, además de corregir un detalle de CSS que afecta al lazy loading.
Cómo detecto cuándo falla una imagen en JavaScript
El truco está en escuchar el evento error directamente sobre el elemento <img>. Cuando la URL del póster devuelve 404 o la propiedad llega como null desde la API de Movie DB, el navegador dispara ese evento y ahí es donde tú entras a actuar [02:10].
Dentro de la función que crea cada tarjeta de película, agregas un addEventListener sobre movieImage escuchando el evento error. Cuando ese error ocurre, llamas a setAttribute('src', ...) con la URL de tu imagen por defecto. Así el navegador reemplaza el póster roto sin que el usuario vea un espacio vacío.
¿Qué evento detecta cuando una imagen no carga en HTML? El evento
errordel elemento<img>. Se dispara cuando el recurso devuelve 404, está corrupto o el src es inválido, y permite ejecutar lógica de fallback.
Por qué el orden del setAttribute importa
Un detalle fácil de pasar por alto: el addEventListener del error debe ir después del setAttribute original que asigna el póster real. Si lo pones antes, corres el riesgo de que el orden de ejecución sobrescriba tu lógica de reemplazo o genere comportamientos confusos. Mantén el listener debajo y tu código queda más predecible [04:30].
Cómo agrego una imagen de fallback cuando el póster no existe
La imagen por defecto puede ser cualquier recurso accesible por URL. En la clase se usa una ilustración tipo astronauta de Platzi que dice "Algo falló", pero lo ideal es que crees tu propio asset o uses uno libre de derechos.
El flujo queda así:
- Asignas el
srcreal de la API consetAttribute. - Agregas el
addEventListener('error', ...)sobre la misma imagen. - Dentro del callback, vuelves a llamar a
setAttribute('src', urlDeFallback).
Al recargar y buscar películas como Vengadores o títulos con pocos resultados como Holly, las cartas que antes mostraban el alt sobre fondo blanco ahora muestran tu ilustración de error. La interfaz se siente completa.
Por qué el lazy loading carga todas las imágenes a la vez
Aquí viene lo interesante. Después de arreglar los pósters faltantes, aparece otro síntoma raro: en la sección de películas por categoría, todas las imágenes se cargan al mismo tiempo aunque tengas el lazy loading activo. ¿Cómo así?
El problema no es JavaScript, es CSS. Cuando una imagen no ha cargado, su height por defecto es prácticamente cero, porque el navegador todavía no sabe sus dimensiones. Si todas las tarjetas miden cero de alto, todas caben en el viewport al mismo tiempo, y el IntersectionObserver reporta isIntersecting: true para cada una. Resultado: tu lazy loader las dispara todas en bloque [09:15].
¿Qué es isIntersecting en el IntersectionObserver? Es una propiedad booleana que indica si el elemento observado está dentro del viewport o del root definido. Cuando es
true, tu callback se ejecuta y puedes cargar el recurso.
Cómo lo compruebas en consola
Una forma rápida de verificarlo es comentar la línea que asigna el src real dentro del lazy loader y dejar solo un console.log(entry.target) para los elementos con isIntersecting en true. Al recargar, ves en la consola que todas las películas se reportan como intersectando, confirmando la hipótesis del alto cero.
Cómo soluciono el lazy loading con min-height en CSS
La cura es darle a cada .movie-img un min-height que reserve espacio aunque la imagen aún no haya cargado. En la clase se prueban varios valores y se aterriza en 175 píxeles como un mínimo razonable que funciona para distintos tamaños de pantalla.
css .movie-img { min-height: 175px; }
Con ese estilo aplicado, cada contenedor ocupa altura desde el primer render. El navegador ahora sí puede calcular qué tarjetas están dentro del viewport y cuáles no, y el IntersectionObserver reporta isIntersecting: true solo para las primeras seis o cuatro visibles, según el ancho del navegador.
Después de aplicar el min-height, vuelves a activar la línea del setAttribute('src', url) dentro del lazy loader y desactivas el console.log. Al recargar con caché limpio y revisar la pestaña Network filtrando por imágenes, solo cargan las pocas tarjetas visibles, y el resto se va sumando conforme haces scroll.
Qué aprendiste sobre optimización de imágenes en el front-end
Este módulo cierra con dos arreglos que conviven en el mismo flujo:
- Fallback con evento error: usas
addEventListener('error')sobre la imagen y reemplazas elsrccuando la API no entrega póster. - Min-height para lazy loading: das altura mínima a los contenedores con CSS para que el
IntersectionObserverpueda discriminar qué está realmente en pantalla.
No puedes hacer que las imágenes carguen más rápido, pero sí controlar cuándo y cómo se cargan según la interacción del usuario. ¿Tú qué imagen de fallback usarías en tu proyecto? Cuéntalo en los comentarios.