Filed under · Web Performance · 2026-08-29 · 6 min read
How I optimize images before shipping a website
Large images are one of the easiest ways to make an otherwise simple website feel slow. The common mistake is uploading the original image from a camera or design tool and letting CSS shrink it visually. A 4000px-wide image displayed inside a 600px card is still a 4000px image being downloaded.
Start with the dimensions
If an image will never appear larger than about 1200px, I usually don't need to ship a 4000px source image to every visitor. Resize the source close to the largest size the website actually needs, then compress it.
Resize before you compress. Don't send a 4000px image to a 400px container.
Let the browser choose the right size
html<img
src="/images/project-800.webp"
srcset="
/images/project-400.webp 400w,
/images/project-800.webp 800w,
/images/project-1200.webp 1200w
"
sizes="(max-width: 768px) 100vw, 800px"
width="800"
height="500"
alt="Project dashboard"
/>- srcset gives the browser multiple image sizes.
- sizes tells it roughly how much screen space the image will use.
- width and height let the browser reserve space before the image finishes loading.
- Reserving that space helps reduce layout shift.
WebP and AVIF
WebP and AVIF can often reduce file size compared with JPEG or PNG while keeping similar visual quality. But I don't convert every asset blindly. Logos, icons, screenshots, illustrations, and photos have different requirements. SVG is usually better for simple vector graphics, while WebP or AVIF are useful for photographic images.
Lazy loading
Images below the first screen usually don't need to load immediately.
html<img
src="/images/gallery.webp"
loading="lazy"
width="800"
height="500"
alt="Project gallery"
/>But I avoid lazy-loading the main hero image because the browser already needs it immediately. For an important above-the-fold image:
html<img
src="/images/hero.webp"
loading="eager"
fetchpriority="high"
width="1200"
height="700"
alt="Portfolio hero"
/>Optimize what the visitor actually downloads, not just what the image looks like after CSS resizes it.