Treat images as an architecture concern, because they are usually the largest bytes on the page. The strategy has three parts: a pipeline, the markup, and perceived speed.
Pipeline:
- Users upload originals once.
- An image CDN (content delivery network) or image service resizes, crops and converts them on the fly. It produces AVIF or WebP with a fallback, and caches the results.
- URLs encode the width and quality, so the client can request exactly what it needs.
Markup:
- Use
srcsetandsizes, so each device downloads a suitable width. - Set explicit
width/heightoraspect-ratio. This prevents layout shift, where content jumps as images load. - Use
loading="lazy"for images below the fold. - Load the hero image, or the first feed image, eagerly with
fetchpriority="high". It is often the LCP element. LCP (Largest Contentful Paint) is when the biggest image or text block appears.
Perceived speed: store a tiny blurred placeholder or a dominant colour with the image metadata. Then the grid looks complete instantly. The API returns the dimensions and placeholder data with each item.
In a framework, a component like next/image wraps most of this. But the API must provide dimensions for it to work well.
- An image CDN resizes images and converts them to modern formats.
srcsetandsizesmake each device download a suitable size.- Set image dimensions to avoid layout shift.
- Lazy load images below the fold, and give the LCP image high priority.
- The API provides placeholder data from the image metadata.
Read more