Optimización de imágenes en la web moderna: formatos, lazy loading y CDN
Formatos de imagen, srcset/sizes, lazy loading nativo y CDN de transformación on-the-fly: la guía técnica completa para dejar de servir imágenes de más.
Las imágenes siguen siendo, con diferencia, el tipo de recurso que más peso añade a una página web media, y en la mayoría de sitios el elemento que decide el LCP es una imagen: un hero, una foto de producto, una portada de artículo. Esto no ha cambiado en años. Lo que sí ha cambiado es que en 2026 ya no hay excusa técnica para servir una imagen sin optimizar: los formatos modernos, el marcado responsive nativo y los CDN de transformación llevan tiempo maduros y con soporte de navegador prácticamente universal.
Formatos en 2026: AVIF, WebP y cuándo sigue teniendo sentido JPEG
La jerarquía de formatos fotográficos está bastante asentada:
- AVIF: el formato con mejor compresión disponible hoy, entre un 30% y un 50% más ligero que un JPEG equivalente a calidad visual similar, y también más eficiente que WebP en la mayoría de fotografías. Su soporte en navegadores ronda ya el 94-95% a nivel global (Chrome, Firefox, Safari 16.1+, Edge, Opera lo decodifican de forma nativa). El coste está en la codificación: generar un AVIF puede tardar entre 5 y 10 veces más que generar un JPEG, así que interesa hacerlo en build o a través de un servicio, nunca en el hilo de una petición en caliente.
- WebP: compresión notablemente mejor que JPEG (en torno a un 25-30%) con soporte prácticamente universal (por encima del 96-97%) y coste de codificación mucho menor que AVIF. Es el candidato perfecto como fallback fiable.
- JPEG: sigue teniendo sentido como última red de seguridad para el escaso porcentaje de navegadores o herramientas (bots, lectores RSS, clientes de correo) que no soportan formatos modernos, y en flujos de trabajo donde no se puede introducir un paso de conversión.
- PNG: resérvalo para lo que de verdad necesita transparencia sin pérdida o gráficos con pocos colores planos (capturas de UI, iconos complejos). Para fotografías es casi siempre la peor opción.
- SVG: para iconos, logotipos e ilustraciones vectoriales. No compite con los formatos anteriores porque no es una imagen rasterizada; escala sin pérdida y suele pesar menos que cualquier alternativa para este tipo de contenido.
La estrategia práctica para fotografías es servir AVIF como primera opción, WebP como fallback y, si el proyecto lo requiere, JPEG como último recurso, dejando que el propio navegador elija el primer formato que soporte:
<picture>
<source srcset="/hero.avif" type="image/avif" />
<source srcset="/hero.webp" type="image/webp" />
<img
src="/hero.jpg"
alt="Descripción real de la imagen"
width="1600"
height="900"
/>
</picture>
Usa <picture> con distintos formatos como el de arriba cuando solo cambias la codificación del mismo recuadro. Resérvalo para art direction de verdad —mostrar un recorte distinto en móvil que en desktop, no solo una versión más pequeña de la misma imagen— cuando además necesites cambiar la composición visual entre breakpoints.
srcset y sizes: que el navegador elija, no tú
srcset le dice al navegador qué variantes de una misma imagen existen; sizes le dice a qué ancho se va a renderizar esa imagen en el layout real. Con esos dos datos, el navegador calcula solo qué archivo descargar según su viewport, densidad de píxeles y velocidad de red, sin que necesites JavaScript ni detección de dispositivo en servidor.
<img
src="/producto-800.avif"
srcset="
/producto-400.avif 400w,
/producto-800.avif 800w,
/producto-1200.avif 1200w,
/producto-2400.avif 2400w
"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
alt="Nombre del producto"
width="800"
height="800"
/>
Con 3-4 variantes de ancho suele ser suficiente para cubrir la mayoría de dispositivos sin generar decenas de archivos que nadie va a servir nunca. Lo importante no es el número exacto de breakpoints, sino que cada uno se corresponda con un tamaño real de renderizado en tu layout, no con tamaños arbitrarios.
Lazy loading nativo: dónde ayuda y dónde te dispara el LCP
El atributo loading="lazy" retrasa la descarga de una imagen hasta que se acerca al viewport, sin necesidad de librerías de terceros ni IntersectionObserver manual. La regla que hay que interiorizar es simple pero se rompe constantemente: nunca apliques loading="lazy" a la imagen que va a ser tu elemento LCP. Si retrasas la descarga del hero, retrasas directamente tu métrica de carga más visible.
<!-- Imagen LCP: eager (o sin atributo, es el valor por defecto) + prioridad alta -->
<img src="/hero.avif" alt="..." fetchpriority="high" width="1600" height="900" />
<!-- Imágenes por debajo del pliegue: lazy, sin penalizar nada -->
<img src="/seccion-2.avif" alt="..." loading="lazy" width="800" height="600" />
Un detalle más reciente y menos conocido: para imágenes con loading="lazy", algunos navegadores ya soportan sizes="auto". Como una imagen lazy no se descarga hasta que el layout ya está resuelto, el navegador puede usar el ancho real renderizado del elemento en lugar de depender de que hayas calculado bien el atributo sizes a mano, eliminando el margen de error humano en ese cálculo.
En resumen, la combinación que exprime mejor la carga es: fetchpriority="high" + carga eager solo en el recurso LCP, loading="lazy" en todo lo demás, y decoding="async" de forma generalizada para que la decodificación de la imagen no bloquee el hilo principal en el momento de pintarla.
Cuándo un CDN de imágenes con transformación on-the-fly merece la pena
Un CDN de imágenes añade una capa de transformación sobre la entrega: en lugar de generar tú mismo cada variante de ancho y formato en build, sirves un original y pides variantes por URL (/foto.jpg?w=800&format=avif&quality=70), y el servicio genera, optimiza y cachea esa variante en el edge la primera vez que se solicita.
Servicios como Cloudflare Images, imgix o Cloudinary resuelven esto con matices distintos: Cloudflare Images resuelve transformación y entrega desde tu propia infraestructura de Cloudflare con un modelo de precio predecible; imgix no almacena nada, se conecta a tu storage existente (S3, GCS) y transforma al vuelo con un conjunto muy amplio de parámetros (recorte inteligente por punto focal, marcas de agua, previsualización de vídeo); Cloudinary añade encima un pipeline más completo de edición y efectos, pensado para catálogos grandes con necesidades de transformación variadas.
La pregunta que decide si necesitas uno no es “¿tengo imágenes?”, es esta:
- No lo necesitas si tu catálogo de imágenes es finito y conocido en build (un blog, una landing, un catálogo de producto pequeño y estable): generar las variantes AVIF/WebP en el propio pipeline de build —con
astro:assets,next/imageo un script consharp— es más simple, más barato y no añade una dependencia externa en el camino crítico. - Sí lo necesitas cuando el volumen o la variabilidad hacen inviable generar todo en build: contenido generado por usuarios (fotos de perfil, marketplaces), catálogos con miles de referencias que cambian constantemente, o aplicaciones que sirven la misma imagen en decenas de combinaciones de tamaño y formato según dispositivo y contexto sin poder anticiparlas todas de antemano.
Checklist de producción
- Formato: AVIF con fallback a WebP (y JPEG como última red de seguridad) para fotografías; SVG para iconos y logotipos.
srcset+sizesalineados con los anchos reales de renderizado en tu layout, no con números arbitrarios.widthyheight(oaspect-ratioexplícito) en toda imagen, sea o no responsive.loading="lazy"en todo excepto en el recurso LCP;fetchpriority="high"sí en el recurso LCP.decoding="async"como valor por defecto.- CDN de transformación solo cuando el volumen o la variabilidad de imágenes lo justifican; generación en build cuando el catálogo es finito y predecible.
Ninguna de estas técnicas es nueva por separado. Lo que las hace efectivas es aplicarlas juntas: un formato mal elegido con un srcset perfecto sigue pesando de más, y un loading="lazy" bien puesto en la imagen equivocada puede empeorar tu LCP en vez de mejorarlo.
Artículos relacionados
WCAG 2.2 explicado: la guía práctica de accesibilidad web para developers
Los 9 criterios nuevos de WCAG 2.2 explicados sin jerga, qué nivel de conformidad te exige realmente la ley y cómo auditar tu web con herramientas reales.
Islands architecture: cómo funciona y por qué está ganando terreno
Hidratar toda una aplicación para que un botón funcione es el problema que la arquitectura de islas vino a resolver. Cómo funciona por dentro, cómo la implementa Astro y qué se pierde a cambio de lo que se gana.
Cómo auditar y mejorar el rendimiento de una web paso a paso
Un método concreto para auditar rendimiento: de los datos de campo (CrUX) al diagnóstico de laboratorio, con un ejemplo de auditoría completo.