Raw <img> tags skip automatic optimization, lazy loading, and responsive sizing. next/image provides WebP/AVIF conversion, blur placeholders, and CLS prevention.
Impact: HIGH (40-80% image size reduction and elimination of Cumulative Layout Shift)
Images are typically the largest assets on a web page. Raw <img> tags force the browser to download full-size images regardless of viewport, cause layout shift (CLS) when they load, and serve unoptimized formats. The next/image component provides:
srcset for the right oneIncorrect (raw img tags):
// ❌ Full-size image downloaded on every device, causes layout shift
export default function ProductCard({ product }) {
return (
<div>
<img src={product.imageUrl} alt={product.name} />
<h3>{product.name}</h3>
</div>
)
}
// ❌ CSS background images skip all optimization
<div style={{ backgroundImage: `url(${hero.url})` }} />
// ❌ Eager loading large images in below-the-fold content
<img src="/huge-banner.jpg" alt="Banner" loading="eager" />Correct (next/image with proper configuration):
import Image from 'next/image'
// ✅ Local images — dimensions inferred automatically
export default function ProductCard({ product }) {
return (
<div>
<Image
src={product.imageUrl}
alt={product.name}
width={400}
height={300}
sizes="(max-width: 768px) 100vw, 400px"
/>
<h3>{product.name}</h3>
</div>
)
}
// ✅ Hero/LCP images — set priority to preload
<Image
src="/hero.jpg"
alt="Welcome to our store"
width={1200}
height={600}
priority // Preloads the image, disables lazy loading
sizes="100vw"
placeholder="blur" // Shows blurred version while loading
blurDataURL={blurHash} // Base64 blur placeholder
/>
// ✅ Fill mode for unknown dimensions (e.g., user uploads)
<div className="relative aspect-video">
<Image
src={user.avatarUrl}
alt={user.name}
fill
className="object-cover"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</div>Configure remote image domains:
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.example.com',
pathname: '/uploads/**',
},
],
},
}Key rules:
width and height (or use fill) — this prevents CLSsizes — tells the browser which image size to download at each viewport widthpriority on LCP images — above-the-fold hero images, product images on landing pagesplaceholder="blur" for a better loading experience on large imagesremotePatterns — not domains (deprecated) — for external imagesDetection hints:
# Find raw img tags that should use next/image
grep -rn "<img " src/ --include="*.tsx" --include="*.jsx" | grep -v "node_modules"
# Find Image components missing sizes prop
grep -rn "<Image" src/ --include="*.tsx" -A 5 | grep -B 3 "width=" | grep -L "sizes="Reference: Next.js Image Optimization · Web.dev CLS Guide
40-80% image size reduction and elimination of Cumulative Layout Shift
BeforeMerge scans your pull requests against this rule and 6+ others. Get actionable feedback before code ships.