Image Best Practices for 2024
TL;DR: Use loading="lazy", decoding="async", specify dimensions to prevent layout shift, use srcset with multiple sizes, and serve WebP with JPEG fallback. That’s 90% of what matters in 2024.
<img
src="image.jpg"
srcset="image.webp?w=400 400w,
image.webp?w=800 800w,
image.webp?w=1200 1200w"
sizes="(max-width: 768px) 100vw, 800px"
loading="lazy"
decoding="async"
width="800"
height="600"
alt="Descriptive alt text"
/>
Core Best Practices for 2024
-
Prevent Layout Shift
- Always specify
widthandheightattributes - Use
aspect-ratioin CSS when dimensions are dynamic - Consider using
object-fit: coverfor variable-size containers
- Always specify
-
Optimize Loading
- Use
loading="lazy"for images below the fold (94%+ browser support) - Add
decoding="async"to help browser prioritization - Preload critical images with
<link rel="preload"> - Consider LQIP (Low Quality Image Placeholders) for hero images
- Use
-
Responsive Images
- Use
srcsetwith width descriptors for responsive images - Provide at least 3-4 size variants (e.g., 400w, 800w, 1200w, 1600w)
- Use the
sizesattribute to help browsers choose correctly - Consider
pictureelement for art direction needs
- Use
-
Modern Formats
- Serve WebP by default (95%+ browser support in 2024)
- Use AVIF for quality-critical images (77%+ support)
- Maintain JPEG fallbacks for legacy support
- Consider JXL for specialized use cases (limited support)
Practical Implementation Examples
Basic Responsive Image
<img
src="https://i.zr.io/ri/i/glacier.jpg?w=800"
srcset="https://i.zr.io/ri/i/glacier.jpg?w=400 400w,
https://i.zr.io/ri/i/glacier.jpg?w=800 800w,
https://i.zr.io/ri/i/glacier.jpg?w=1200 1200w"
sizes="(max-width: 768px) 100vw, 800px"
loading="lazy"
decoding="async"
width="800"
height="1200"
alt="Glacier landscape"
/>
Format-Aware Picture Element
<picture>
<source
type="image/avif"
srcset="image.avif?w=400 400w,
image.avif?w=800 800w,
image.avif?w=1200 1200w"
sizes="(max-width: 768px) 100vw, 800px"
/>
<source
type="image/webp"
srcset="image.webp?w=400 400w,
image.webp?w=800 800w,
image.webp?w=1200 1200w"
sizes="(max-width: 768px) 100vw, 800px"
/>
<img
src="image.jpg?w=800"
width="800"
height="600"
loading="lazy"
decoding="async"
alt="Description"
/>
</picture>
Performance Optimization
-
Critical Images
<link rel="preload" as="image" href="hero.webp" imagesrcset="hero.webp?w=400 400w, hero.webp?w=800 800w" imagesizes="100vw" /> -
Lazy Loading with LQIP
<div class="image-wrapper" style="background-image: url('tiny-blur.jpg');"> <img src="full-image.jpg?w=1200" loading="lazy" class="fade-in" onload="this.classList.add('loaded')" /> </div>.image-wrapper { background-size: cover; background-position: center; } .fade-in { opacity: 0; transition: opacity 0.3s; } .fade-in.loaded { opacity: 1; }
Common Patterns and Solutions
-
Fixed-Size Container with Variable Image
.image-container { aspect-ratio: 16/9; width: 100%; } .image-container img { width: 100%; height: 100%; object-fit: cover; } -
Responsive Gallery Images
.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 1rem; } .gallery img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 1; }
Browser Support Considerations (2024)
loading="lazy": 94%+ global supportdecoding="async": 95%+ global support- WebP: 95%+ global support
- AVIF: 77%+ global support
aspect-ratio: 95%+ global supportobject-fit: 98%+ global support
Performance Testing
- Use Lighthouse in Chrome DevTools
- Monitor Core Web Vitals in Search Console
- Test Largest Contentful Paint (LCP) for hero images
- Check Cumulative Layout Shift (CLS) scores
- Verify lazy loading behavior with Performance tab
Common Mistakes to Avoid
- Don’t skip
widthandheightattributes - Don’t lazy-load above-the-fold images
- Don’t serve oversized images to mobile devices
- Don’t forget to compress and optimize images
- Don’t ignore
alttext for accessibility - Don’t rely on client-side resizing
- Don’t use JPEG for images with text or sharp edges
Conclusion
Focus on the fundamentals: prevent layout shift, optimize loading, use responsive images, and serve modern formats. The basics (proper dimensions, lazy loading, and srcset) will get you 90% of the way there. Test thoroughly across devices and monitor performance metrics to ensure your implementation works as intended.