Imágenes y rendimiento: lazy, fetchpriority y srcset
Las imágenes son, habitualmente, el recurso más pesado de una página web. HTML moderno te da atributos potentes para controlar exactamente cuándo, cómo y en qué calidad se cargan. Sin una línea de JavaScript.
loading: carga diferida nativa
El atributo loading controla cuándo el navegador descarga la imagen.
<!-- Carga inmediata (comportamiento por defecto) -->
<img src="hero.jpg" alt="Portada" loading="eager" />
<!-- Carga diferida: solo cuando esté cerca del viewport -->
<img src="foto-al-final.jpg" alt="Foto" loading="lazy" />
¿Cuándo usar lazy?
Usa loading="lazy" en todas las imágenes que no sean visibles al cargar la página: imágenes en mitad del artículo, en el footer, en galerías largas, etc.
No uses lazy en la imagen principal (el hero o la primera imagen visible). Hacerlo retrasa la carga y penaliza el LCP (Largest Contentful Paint), una métrica de Core Web Vitals.
<!-- ✅ Hero: eager (o simplemente sin el atributo) -->
<img src="hero.jpg" alt="Hero" loading="eager" />
<!-- ✅ Resto de imágenes -->
<img src="seccion-2.jpg" alt="Sección 2" loading="lazy" />
<img src="seccion-3.jpg" alt="Sección 3" loading="lazy" />
fetchpriority: controla la prioridad de descarga
El navegador decide por sí solo qué recursos descarga primero. Con fetchpriority puedes darle pistas explícitas.
<!-- Alta prioridad: imagen crítica para el LCP -->
<img src="hero.jpg" alt="Hero" fetchpriority="high" />
<!-- Baja prioridad: imagen decorativa o fuera del viewport -->
<img src="decorativa.jpg" alt="" fetchpriority="low" />
<!-- Auto: el navegador decide (comportamiento por defecto) -->
<img src="normal.jpg" alt="Imagen" fetchpriority="auto" />
El combo ideal para el hero
La imagen principal de la página debería tener siempre este combo:
<img
src="hero.jpg"
alt="Descripción del hero"
loading="eager"
fetchpriority="high"
decoding="sync"
/>
Y el resto de imágenes:
<img
src="contenido.jpg"
alt="Descripción"
loading="lazy"
fetchpriority="low"
decoding="async"
/>
decoding: cuándo decodificar la imagen
La decodificación de una imagen puede bloquear el hilo principal del navegador.
<!-- sync: decodifica antes de mostrar el resto de la página (hero crítico) -->
<img src="hero.jpg" alt="Hero" decoding="sync" />
<!-- async: decodifica en paralelo, sin bloquear el render -->
<img src="foto.jpg" alt="Foto" decoding="async" />
En la práctica, decoding="async" es seguro para la mayoría de imágenes.
srcset y sizes: imágenes responsivas
Una sola imagen en tamaño grande para todos los dispositivos es un desperdicio. Con srcset le dices al navegador qué versiones existen, y con sizes le dices cuánto espacio ocupa la imagen en pantalla.
<img
src="foto-800.jpg"
srcset="
foto-400.jpg 400w,
foto-800.jpg 800w,
foto-1200.jpg 1200w
"
sizes="
(max-width: 600px) 100vw,
(max-width: 1024px) 50vw,
800px
"
alt="Foto responsiva"
loading="lazy"
/>
Cómo leer sizes:
- En pantallas ≤ 600px → la imagen ocupa el 100% del ancho.
- En pantallas ≤ 1024px → ocupa el 50% del ancho.
- En el resto → ocupa exactamente 800px.
El navegador usa esta información para elegir la versión del srcset más eficiente.
<picture>: control total sobre el formato
<picture> va un paso más allá: permite servir formatos distintos según lo que soporte el navegador, y también diferentes imágenes según el tamaño de pantalla (art direction).
Servir formatos modernos con fallback
<picture>
<!-- AVIF: el más eficiente, soporte moderno -->
<source srcset="foto.avif" type="image/avif" />
<!-- WebP: segunda opción, soporte amplio -->
<source srcset="foto.webp" type="image/webp" />
<!-- JPG: fallback universal -->
<img src="foto.jpg" alt="Descripción" loading="lazy" />
</picture>
El navegador prueba los <source> en orden y usa el primero que soporta. El <img> es el fallback obligatorio.
Art direction: imagen diferente según el dispositivo
<picture>
<!-- En móvil: imagen vertical recortada -->
<source
media="(max-width: 600px)"
srcset="hero-mobile.jpg"
/>
<!-- En escritorio: imagen horizontal completa -->
<img src="hero-desktop.jpg" alt="Hero" />
</picture>
Resumen: la guía rápida
| Imagen | loading | fetchpriority | decoding |
|---|---|---|---|
| Hero / LCP | eager | high | sync |
| Contenido visible | eager | auto | async |
| Fuera del viewport | lazy | low | async |
¿Qué hemos aprendido?
loading="lazy"difiere imágenes no visibles sin nada de JavaScript.fetchpriority="high"avisa al navegador de que una imagen es crítica para el LCP.decoding="async"libera el hilo principal durante la decodificación.srcset+sizessirven la resolución correcta según el dispositivo.<picture>permite servir formatos modernos (AVIF, WebP) con fallback automático.
Siguiente paso
En la próxima lección veremos <dialog> y la Popover API: cómo crear modales, tooltips y paneles flotantes que el navegador gestiona de forma nativa.