Modern Formats
Modern Formats
Use next-gen image formats for better compression.
WebP vs JPEG vs PNG
| Format | Compression | Transparency | Animation | Browser Support |
|---|---|---|---|---|
| JPEG | Lossy | No | No | 100% |
| PNG | Lossless | Yes | No | 100% |
| WebP | Both | Yes | Yes | 97%+ |
| AVIF | Both | Yes | Yes | 92%+ |
Implementing WebP
// Serve WebP with fallback
function OptimizedImage({ src, alt, width, height }) {
return (
<picture>
<source srcSet={`${src}.webp`} type="image/webp" />
<source srcSet={`${src}.jpg`} type="image/jpeg" />
<img
src={`${src}.jpg`}
alt={alt}
width={width}
height={height}
loading="lazy"
/>
</picture>
);
}
// Usage
<OptimizedImage
src="/images/hero"
alt="Hero image"
width={1200}
height={600}
/>
AVIF Support
function NextGenImage({ src, alt, width, height }) {
return (
<picture>
<source srcSet={`${src}.avif`} type="image/avif" />
<source srcSet={`${src}.webp`} type="image/webp" />
<img
src={`${src}.jpg`}
alt={alt}
width={width}
height={height}
loading="lazy"
decoding="async"
/>
</picture>
);
}
Image Processing with Sharp
// Server-side image processing
const sharp = require('sharp');
async function processImage(inputPath, outputPath) {
await sharp(inputPath)
.resize(1200, 630, { fit: 'cover' })
.webp({ quality: 80 })
.toFile(`${outputPath}.webp`);
await sharp(inputPath)
.resize(1200, 630, { fit: 'cover' })
.jpeg({ quality: 80, progressive: true })
.toFile(`${outputPath}.jpg`);
}
Quality Settings
// Recommended quality settings
const qualitySettings = {
webp: { quality: 80, effort: 4 },
jpeg: { quality: 80, progressive: true },
avif: { quality: 65, effort: 4 },
png: { compressionLevel: 6 },
};
Responsive Images
Responsive Images
Serve appropriately sized images for different devices.
srcset and sizes
function ResponsiveImage({ src, alt }) {
return (
<img
src={`${src}-800.jpg`}
srcset={
`${src}-400.jpg 400w,
${src}-800.jpg 800w,
${src}-1200.jpg 1200w,
${src}-1600.jpg 1600w`
}
sizes={
"(max-width: 640px) 100vw,
(max-width: 1024px) 50vw,
33vw"
}
alt={alt}
loading="lazy"
width={800}
height={600}
/>
);
}
Art Direction
function HeroImage() {
return (
<picture>
{/* Mobile: cropped close-up */}
<source
media="(max-width: 768px)"
srcSet="/hero-mobile.webp"
type="image/webp"
/>
<source
media="(max-width: 768px)"
srcSet="/hero-mobile.jpg"
/>
{/* Desktop: full image */}
<source
srcSet="/hero-desktop.webp"
type="image/webp"
/>
<img
src="/hero-desktop.jpg"
alt="Hero"
className="hero-image"
/>
</picture>
);
}
Image CDN
// Using an image CDN like Cloudinary or imgix
function CDNOptimizedImage({ publicId, alt, width, height }) {
const baseUrl = 'https://res.cloudinary.com/demo/image/upload';
return (
<img
src={`${baseUrl}/w_${width},h_${height},f_auto,q_auto/${publicId}`}
srcset={
`${baseUrl}/w_400,h_300,f_auto,q_auto/${publicId} 400w,
${baseUrl}/w_800,h_600,f_auto,q_auto/${publicId} 800w,
${baseUrl}/w_1200,h_900,f_auto,q_auto/${publicId} 1200w`
}
sizes="(max-width: 768px) 100vw, 50vw"
alt={alt}
width={width}
height={height}
loading="lazy"
/>
);
}
CSS Image Optimization
/* Object-fit for consistent sizing */
.image-container {
width: 100%;
height: 300px;
overflow: hidden;
}
.image-container img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Content visibility for below-fold images */
.below-fold-images {
content-visibility: auto;
contain-intrinsic-size: 0 500px;
}
Image CDN
Image CDN
Use a CDN for automatic image optimization.
Cloudinary
function CloudinaryImage({ publicId, width, height }) {
const url = `https://res.cloudinary.com/demo/image/upload`;
return (
<img
src={`${url}/w_${width},h_${height},f_auto,q_auto/${publicId}`}
srcset={
`${url}/w_400,f_auto/${publicId} 400w,
${url}/w_800,f_auto/${publicId} 800w,
${url}/w_1200,f_auto/${publicId} 1200w`
}
sizes="(max-width: 768px) 100vw, 50vw"
alt=""
loading="lazy"
/>
);
}
// Transformations
const transformations = {
thumbnail: 'w_150,h_150,c_fill,g_face',
card: 'w_400,h_300,c_fill',
hero: 'w_1920,h_1080,c_fill',
avatar: 'w_100,h_100,c_fill,g_face,r_max',
};
imgix
function ImgixImage({ src, alt, width, height }) {
const params = new URLSearchParams({
w: width,
h: height,
fit: 'crop',
auto: 'format,compress',
});
return (
<img
src={`${src}?${params}`}
srcset={
`${src}?w=400&auto=format 400w,
${src}?w=800&auto=format 800w,
${src}?w=1200&auto=format 1200w`
}
sizes="(max-width: 768px) 100vw, 50vw"
alt={alt}
loading="lazy"
/>
);
}
Self-Hosted with Next.js
// next.config.js
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
minimumCacheTTL: 60 * 60 * 24 * 30, // 30 days
},
};
// Component
import Image from 'next/image';
function OptimizedImage({ src, alt }) {
return (
<Image
src={src}
alt={alt}
width={800}
height={600}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQ..."
/>
);
}
Best Practices
- Use modern formats: WebP/AVIF with fallbacks
- Implement srcset: Serve appropriate sizes
- Lazy load: Use loading="lazy" for below-fold
- Set dimensions: Prevent CLS
- Use CDN: Automatic optimization and caching
- Compress: Reduce file sizes
- Cache: Set proper cache headers
Practice Problems
Create a reusable React component implementing Image Optimization. Include proper state management and accessibility.
Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where neededWrite unit and integration tests for Image Optimization using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize Image Optimization for performance. Consider memoization, code splitting, and bundle size.
Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysisQuiz
1. What is the main benefit of WebP over JPEG?
2. What does srcset allow?
3. Why use an image CDN?
4. What is art direction in responsive images?
5. Why set image dimensions?
Flashcards
Question
What is WebP?
Click to reveal answer
Answer
A modern image format that provides better compression than JPEG/PNG with support for transparency and animation.
Question
What does srcset do?
Click to reveal answer
Answer
Allows the browser to choose the most appropriate image based on viewport size and device pixel ratio.
Question
What is art direction?
Click to reveal answer
Answer
Serving different image crops optimized for different viewport sizes using the <picture> element.
Question
Why use an image CDN?
Click to reveal answer
Answer
Automatic optimization, resizing, format conversion, and global caching for faster delivery.
Question
What is Image Optimization?
Click to reveal answer
Answer
Image Optimization is a key concept in frontend development.
Revision Notes
Key Takeaways
- 1.WebP and AVIF provide better compression than JPEG/PNG
- 2.srcset enables responsive images for different viewports
- 3.Image CDNs handle optimization automatically
- 4.Art direction serves different crops for different viewports
- 5.Always set dimensions to prevent CLS
Interview Tips
- •Explain the benefits of WebP over JPEG
- •Discuss how srcset and sizes work together
- •Know when to use art direction vs responsive sizing
Cheat Sheet
Image Optimization Cheat Sheet
Modern Formats
- WebP: 25-34% smaller than JPEG
- AVIF: Even better compression
- Use
for fallbacks
Responsive Images
<img
srcSet="img-400.jpg 400w, img-800.jpg 800w"
sizes="(max-width: 768px) 100vw, 50vw"
/>
Best Practices
- Use WebP/AVIF with fallbacks
- Implement srcset for responsive
- Lazy load below-fold images
- Set width/height for CLS
- Use CDN for optimization
- Compress to 80% quality