Performance Optimization
Master image performance optimization. Learn about lazy loading, preloading, preventing layout shift, and improving Core Web Vitals.
Core Web Vitals
Images significantly impact Core Web Vitals, Google's key metrics for user experience. Proper image optimization directly improves your SEO ranking.
LCP
Largest Contentful Paint
Measures loading performance. Images are often the LCP element. Target: < 2.5 seconds.
CLS
Cumulative Layout Shift
Measures visual stability. Images without dimensions cause layout shifts. Target: < 0.1.
FID/INP
Interaction Responsiveness
Measures interactivity. Large images can block the main thread during decode.
Lazy Loading
Lazy loading defers the loading of off-screen images until the user scrolls near them. This improves initial page load time and saves bandwidth.
<!-- Native lazy loading (recommended) -->
<img
src="https://cdn.optimage.com/col_abc123/768/image.webp"
srcset="..."
sizes="100vw"
alt="Description"
loading="lazy"
decoding="async"
/>When to Use Lazy Loading
- ✓Images below the fold (not visible on initial load)
- ✓Image galleries and carousels
- ✓Product listings and grids
- ✓Blog post content images
When NOT to Lazy Load
- ✗Hero images and banners (above the fold)
- ✗LCP (Largest Contentful Paint) elements
- ✗Images visible in the initial viewport
Preloading Critical Images
For above-the-fold images (especially LCP elements), preload them to start downloading early:
<!-- In <head> section -->
<link
rel="preload"
as="image"
href="https://cdn.optimage.com/col_hero/1280/banner.webp"
imagesrcset="
https://cdn.optimage.com/col_hero/320/banner.webp 320w,
https://cdn.optimage.com/col_hero/768/banner.webp 768w,
https://cdn.optimage.com/col_hero/1280/banner.webp 1280w
"
imagesizes="100vw"
/>Using fetchpriority
The fetchpriority attribute tells the browser how important an image is relative to other resources:
<!-- High priority for LCP image -->
<img
src="https://cdn.optimage.com/col_hero/768/banner.webp"
srcset="..."
sizes="100vw"
alt="Hero banner"
loading="eager"
fetchpriority="high"
decoding="sync"
/>
<!-- Low priority for decorative images -->
<img
src="https://cdn.optimage.com/col_bg/768/pattern.webp"
alt=""
loading="lazy"
fetchpriority="low"
decoding="async"
/>Preventing Layout Shift (CLS)
Layout shift occurs when images load without reserved space, pushing content around. Always reserve space for images to achieve a good CLS score.
Method 1: Width and Height Attributes
<!-- Browser calculates aspect ratio from width/height -->
<img
src="https://cdn.optimage.com/col_abc123/768/photo.webp"
width="1600"
height="900"
alt="Photo"
class="w-full h-auto"
/>Method 2: CSS aspect-ratio
<!-- Using CSS aspect-ratio property -->
<img
src="https://cdn.optimage.com/col_abc123/768/photo.webp"
alt="Photo"
class="w-full"
style="aspect-ratio: 16 / 9;"
/>
<!-- Or with Tailwind CSS -->
<img
src="..."
alt="Photo"
class="w-full aspect-video object-cover"
/>Method 3: Container with Padding
<!-- Legacy method (still works everywhere) -->
<div class="relative" style="padding-bottom: 56.25%;">
<img
src="..."
alt="Photo"
class="absolute inset-0 w-full h-full object-cover"
/>
</div>Tip: Modern browsers automatically calculate aspect ratio from width/height attributes, even with width: 100% CSS. This is the simplest and most reliable method.
Image Decoding
The decoding attribute controls how image decoding affects the main thread:
| Value | Behavior | Use Case |
|---|---|---|
| sync | Decode immediately, may block | Critical LCP images |
| async | Decode in background | Most images (default) |
| auto | Browser decides | When unsure |
<!-- Critical image: decode synchronously -->
<img src="hero.webp" decoding="sync" loading="eager" />
<!-- Non-critical image: decode asynchronously -->
<img src="gallery-item.webp" decoding="async" loading="lazy" />CDN and Caching
OPTIMAGE serves all images from Cloudflare's global CDN with optimal caching:
- •Global edge locations: Images served from the nearest data center
- •HTTP/2 and HTTP/3: Faster multiplexed connections
- •Long cache headers: Images cached in browser and CDN edge
- •Immutable URLs: Each image has a unique, cacheable URL
Cache Headers
Cache-Control: public, max-age=31536000, immutable
Content-Type: image/webpNote: OPTIMAGE images are immutable—the content at a URL never changes. If you need to update an image, upload a new one with a different slug.
Optimization Checklist
Use this checklist to ensure your images are fully optimized:
For All Images
- Use WebP format (automatic with OPTIMAGE)
- Include srcset with appropriate sizes
- Set sizes attribute matching your layout
- Add width and height or aspect-ratio
- Include descriptive alt text
For Above-the-Fold Images
- Set
loading="eager" - Set
fetchpriority="high"for LCP - Consider
decoding="sync"for hero images - Add
<link rel="preload">in head
For Below-the-Fold Images
- Set
loading="lazy" - Set
decoding="async" - Consider
fetchpriority="low"for decorative images
Example: Fully Optimized Page
<!DOCTYPE html>
<html>
<head>
<!-- Preload LCP image -->
<link
rel="preload"
as="image"
href="https://cdn.optimage.com/col_hero/1280/banner.webp"
imagesrcset="
https://cdn.optimage.com/col_hero/768/banner.webp 768w,
https://cdn.optimage.com/col_hero/1280/banner.webp 1280w
"
imagesizes="100vw"
/>
</head>
<body>
<!-- Hero (LCP element) -->
<img
src="https://cdn.optimage.com/col_hero/768/banner.webp"
srcset="..."
sizes="100vw"
width="1920"
height="1080"
alt="Welcome to our site"
loading="eager"
fetchpriority="high"
decoding="sync"
class="w-full h-auto"
/>
<!-- Product grid -->
<div class="grid grid-cols-3 gap-4">
<img
src="https://cdn.optimage.com/col_products/768/product-1.webp"
srcset="..."
sizes="33vw"
width="800"
height="800"
alt="Product 1"
loading="lazy"
decoding="async"
class="w-full aspect-square object-cover"
/>
<!-- More products... -->
</div>
</body>
</html>