Switch Language
Toggle Theme

Next.js Image Optimization Complete Guide: Using the Image Component the Right Way

Lighthouse test score: 62.

Staring at that number on my screen, I froze for several seconds. After two weeks of work on this Next.js project, the performance score barely passed. Opening the Performance tab, the biggest issue was right there—LCP (Largest Contentful Paint) at 4.8 seconds, all dragged down by images.

To be honest, I was stunned. I thought using Next.js meant automatic optimization. Then I checked the code—that big Hero image on the homepage was still using the primitive <img> tag. The e-commerce listing page with dozens of product images, all pulling full-resolution images directly from the server, each one 3-4MB.

Later I realized that while Next.js is powerful, image optimization only works if you actively use its Image component. Use it right, and you can reduce image sizes by 60-80% and bring LCP down from 4 seconds to under 2 seconds.

The problem is, many people like me still run into issues even after using the Image component. Remote images throw “Un-configured Host” errors, pages jump around as images load, and there’s a bunch of configuration options with no clear guidance. In this article, I’ll share all the pitfalls I’ve encountered and their solutions, teaching you from scratch how to properly use the Next.js Image component.

Why Use the Next.js Image Component?

Three Major Pitfalls of Regular img Tags

You might think, isn’t an image just <img src="xxx">? I thought so too at first. Until performance testing revealed how big of a problem it was.

First pitfall: No format optimization, wasting bandwidth

With regular img tags, whatever format you give it is what it displays. You upload a 3MB PNG, users download 3MB. Modern browsers basically all support WebP, which can be 30% smaller than JPEG, and browsers supporting AVIF can save another 40%. But img tags don’t care about any of that—they just dutifully load whatever file you specify.

Second pitfall: Same image for all screen sizes

This is especially obvious on mobile. Your site has 2000x1500 high-res images, users’ phone screens are only 375px wide, but they still download the full-size image, and then the browser scales it down. Wasted bandwidth and slow loading.

Third pitfall: Layout shift, frustrating to watch

You’ve definitely experienced this: you open a webpage, about to click a button, an image suddenly loads, the whole page jumps down, and you clicked something else. This is the CLS (Cumulative Layout Shift) issue. Google lists it as one of the Core Web Vitals metrics, directly affecting your SEO ranking.

The Image Component’s Automatic Optimization

The Next.js Image component is specifically designed to solve these problems. It’s not just a simple img tag wrapper, but a complete image optimization solution.

Automatic format selection

The Image component checks the user’s browser Accept request header and automatically determines which formats the browser supports. Supports AVIF? Serve AVIF. Supports WebP? Serve WebP. Neither supported? Serve the original format. This logic is completely automatic—you don’t need to write a single line of code.

I tested this before: a 500KB JPEG, automatically converted to WebP became 180KB, converted to AVIF only 120KB. Think about it—dozens or hundreds of images on a website, how much bandwidth that saves.

Responsive loading

The Image component automatically generates and loads appropriately sized images based on the user’s device screen size. Mobile users see the 375px width version, desktop users see the 1920px version. This feature is called srcset—regular img tags can do it too, but you’d have to manually write tons of configuration. The Image component handles it all automatically.

Lazy loading

By default, the Image component only loads images that appear in the viewport. Images at the bottom of the page only start loading when users scroll there. This feature dramatically reduces the initial load data volume, making pages open much faster.

Data shows that properly using the Next.js Image component can reduce image sizes by 60-80%, keep LCP metrics under 2.5 seconds, and bring CLS close to zero. These aren’t theoretical numbers—they’re what I measured in actual projects.

Basic Usage: Local Images vs Remote Images

When first using the Image component, many people (including me) are most confused by: why do some images work directly while others throw errors? It’s mainly because local and remote images are handled differently.

Local Images: The Simplest Scenario

Local images are image files stored in your project, with two common approaches.

Method 1: import (Recommended)

import heroImage from '/public/images/hero.jpg'
import Image from 'next/image'

export default function Home() {
  return (
    <Image
      src={heroImage}
      alt="Hero image"
    />
  )
}

This method is most hassle-free. Next.js automatically reads the image dimensions during build time, so you don’t even need to write width and height. I basically use this method for all local images now.

Method 2: Direct path

<Image
  src="/images/hero.jpg"
  width={1920}
  height={1080}
  alt="Hero image"
/>

If your images are in the public folder, you can also write the path directly. But with this method, you must manually specify width and height—forgetting will cause errors.

Remote Images: Where Most Mistakes Happen

Remote images are images loaded from external URLs, like when your images are stored on cloud storage services. This scenario most easily causes problems.

Common error: “Un-configured Host”

<Image
  src="https://images.unsplash.com/photo-123456"
  width={800}
  height={600}
  alt="Sample image"
/>

If you write it like this directly, nine times out of ten you’ll see this error:

Error: Invalid src prop (https://images.unsplash.com/photo-123456) on `next/image`, 
hostname "images.unsplash.com" is not configured under images in your `next.config.js`

Why does this happen? Next.js worries that malicious users might exploit your server to optimize images from arbitrary URLs, freeloading off your server resources. So it requires you to explicitly declare which domain images are allowed to be optimized.

The right way: Configure remotePatterns

Add this configuration to next.config.js (recommended for Next.js 14+):

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.unsplash.com',
        port: '',
        pathname: '/**',
      },
      {
        protocol: 'https',
        hostname: 's3.amazonaws.com',
        port: '',
        pathname: '/my-bucket/**',
      },
    ],
  },
}

module.exports = nextConfig

What each configuration item means:

  • protocol: https or http, usually https
  • hostname: Image domain, must match exactly
  • port: Port number, usually left empty
  • pathname: Path matching rule, /** means all paths, or you can limit to specific paths

Remember to restart the dev server after configuring—config file changes require a restart to take effect. The first time I changed the config without restarting, thinking it didn’t work, wasted half an hour.

Old configuration method (not recommended)

If you see some tutorials using domains configuration:

module.exports = {
  images: {
    domains: ['images.unsplash.com', 's3.amazonaws.com'],
  },
}

This approach has been deprecated since Next.js 14. While it still works now, it’s recommended to switch to remotePatterns. Because remotePatterns is more secure and can limit specific path ranges.

Why Width and Height Must Be Specified

Whether local or remote images, except when using the import method, you must manually specify width and height. This is to prevent CLS layout shift.

Before loading an image, the browser needs to know how much space it will occupy so it can reserve it in advance. Without knowing dimensions, the browser can only adjust the layout after the image downloads, causing the page to jump.

Some might wonder: my images are responsive, the width needs to change with screen size, how do I specify fixed width and height? We’ll solve this with the fill attribute later.

Solving Layout Shift Issues (CLS Optimization)

Pages jumping around is really annoying. On a news site I built before, users complained most about “trying to click a headline, the image loads, and I clicked on an ad instead.” Later, when I carefully studied the CLS metric, I realized how important this issue is.

What is CLS and Why It Matters

CLS (Cumulative Layout Shift) translates to cumulative layout shift. Simply put, it’s the degree to which element positions suddenly move during page loading.

Google lists CLS as one of the three Core Web Vitals metrics, directly affecting your SEO ranking. A CLS score over 0.1 is considered poor, below 0.1 is good. Think about it—a webpage with a dozen or twenty images, each making the page jump when loading, how can CLS not be high?

More importantly is user experience. When I browse webpages myself, if I encounter pages that keep jumping around, I basically just close them immediately, with no interest in reading the content.

How the Image Component Prevents CLS

The core principle of how the Next.js Image component prevents CLS is simple: reserve space in advance.

When you set width and height on an Image component, the browser reserves the corresponding size blank area on the page before the image downloads. When the image loads, it just fills in directly—the page layout doesn’t change at all.

<Image
  src="/product.jpg"
  width={400}
  height={300}
  alt="Product image"
/>

With this code, the browser first draws a 400x300 placeholder box on the page, then starts loading the image. CLS value goes straight to zero.

The problem is, modern webpages all use responsive design, where image width needs to change with screen size. Fixed width and height approach isn’t enough.

The Right Way for Responsive Images: fill Attribute

For responsive images, Next.js provides the fill attribute. This attribute makes images fill the entire parent container, with dimensions controlled by CSS.

<div style={{ position: 'relative', width: '100%', height: '400px' }}>
  <Image
    src="/hero.jpg"
    fill
    style={{ objectFit: 'cover' }}
    alt="Hero image"
  />
</div>

Note several key points:

  1. Parent container must set position: relative: So the image knows what to fill relative to
  2. Parent container must have explicit height: Can’t be height: auto, must be a specific value or percentage
  3. Use objectFit to control image fitting: cover crops the image to fill the container, contain displays completely but may have whitespace

This way, the browser sees the parent container’s height and can reserve space in advance, still preventing CLS.

sizes Attribute: Tell the Browser What Size Image to Load

When using the fill attribute, you also need to pair it with the sizes attribute, otherwise Next.js doesn’t know what size images to generate.

<div style={{ position: 'relative', width: '100%', height: '400px' }}>
  <Image
    src="/hero.jpg"
    fill
    sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
    style={{ objectFit: 'cover' }}
    alt="Hero image"
  />
</div>

What the sizes attribute means:

  • When screen width ≤768px, image occupies 100% viewport width
  • When screen width is between 768px-1200px, image occupies 50% viewport width
  • When screen width >1200px, image occupies 33% viewport width

Next.js generates multiple different-sized images based on this configuration, and the browser automatically selects the most appropriate one. Mobile users don’t need to download desktop-sized large images—saves bandwidth and is faster.

Real Cases: Handling Different Scenarios

Hero Image (Full-width above-the-fold)

<div style={{ position: 'relative', width: '100%', height: '60vh' }}>
  <Image
    src="/hero.jpg"
    fill
    priority
    sizes="100vw"
    style={{ objectFit: 'cover' }}
    alt="Hero image"
  />
</div>

Here we use the priority attribute (covered later) to make the above-the-fold Hero image load first. sizes="100vw" means the image always fills the entire viewport width.

Article Thumbnails (Fixed Size)

<Image
  src={post.thumbnail}
  width={300}
  height={200}
  alt={post.title}
/>

Thumbnail dimensions are fixed, directly using width and height is simplest.

Product List (Responsive Grid)

<div style={{ position: 'relative', width: '100%', paddingBottom: '100%' }}>
  <Image
    src={product.image}
    fill
    sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
    style={{ objectFit: 'cover' }}
    alt={product.name}
  />
</div>

Using paddingBottom: '100%' creates a square container (responsive 1:1 ratio), suitable for product image display. Images occupy different widths on different screens—one per row on mobile, two per row on tablet, three per row on desktop.

Core Performance Optimization Configuration

Having mastered basic usage and CLS optimization, let’s discuss several key configurations that can take performance to the next level.

priority: Critical Above-the-Fold Images Should Load First

By default, images in the Image component are all lazy loaded, only starting to load when scrolled into the viewport. But for critical above-the-fold elements like Hero images and logos, you definitely want them to load immediately, otherwise users see a blank space.

This is when you use the priority attribute:

<Image
  src="/hero.jpg"
  width={1920}
  height={1080}
  priority
  alt="Hero image"
/>

With priority added, Next.js will:

  1. Cancel lazy loading and start loading the image immediately
  2. Insert a preload tag in the HTML <head>, telling the browser this image is important
  3. LCP (Largest Contentful Paint) metric will significantly improve

One time I did performance optimization, just adding priority to the homepage Hero image brought LCP down from 3.8 seconds to 2.1 seconds. Immediate effect.

When to use priority?

  1. Homepage Hero image
  2. Site logo (if large)
  3. Article detail page header image
  4. Any image that might become the LCP element

You might think, what if I add priority to all images for faster loading? Don’t. priority makes the browser download immediately—if 20 images on the page all have it, the browser downloading 20 images simultaneously will actually slow things down. Use this attribute sparingly, only adding it to the most critical images.

Next.js 16 Changes

Speaking of which, I should mention the Next.js 16 update (currently still RC version). The priority attribute is changing to the preload attribute. If you’re using the latest version, the code should change to:

<Image
  src="/hero.jpg"
  width={1920}
  height={1080}
  preload
  alt="Hero image"
/>

Or a more flexible approach, using loading="eager" and fetchPriority="high":

<Image
  src="/hero.jpg"
  width={1920}
  height={1080}
  loading="eager"
  fetchPriority="high"
  alt="Hero image"
/>

loading: Control Loading Strategy

The loading attribute has two values:

  • lazy (default): Lazy loading, image starts downloading when entering viewport
  • eager: Load immediately, regardless of whether image is in viewport

In most cases, the default lazy is sufficient. Only critical above-the-fold images need to be changed to eager.

// Related article images at page bottom, use default lazy
<Image src="/related-1.jpg" width={300} height={200} alt="Related post" />

// Main content image above the fold, change to eager
<Image src="/main-content.jpg" width={800} height={600} loading="eager" alt="Main content" />

quality: Balancing Quality and Size

The quality attribute controls image compression quality, ranging from 1-100, with a default value of 75.

<Image
  src="/product.jpg"
  width={800}
  height={600}
  quality={90}
  alt="Product image"
/>

Higher quality means clearer images, but larger files. Here’s an empirical value:

  • Critical above-the-fold images: quality={90}, ensure clarity
  • General content images: quality={75} (default), balance quality and size
  • Thumbnails, background images: quality={60}, save bandwidth

I tested that reducing quality from 90 to 75, the difference is almost imperceptible to the naked eye, but file size can be reduced by about 30%. Reducing from 75 to 60, it’s still acceptable on regular screens, saving another 20% in size.

Important update: Starting with Next.js 16, quality becomes a required field. This is to prevent malicious users from requesting images with various different quality levels via URL parameters, consuming server resources. After upgrading to 16, remember to add the quality attribute to every Image component.

Automatic Format Selection: WebP vs AVIF

This feature is completely automatic, you don’t need to configure anything. Next.js checks the browser’s Accept request header and automatically selects the most appropriate format.

  • Browser supports AVIF → Output AVIF (smallest, but slow encoding)
  • Browser supports WebP → Output WebP (smaller, good compatibility)
  • Neither supported → Output original format (JPEG/PNG)

AVIF is 30-40% smaller than WebP, but compatibility is slightly worse. However, mainstream browsers (Chrome 85+, Firefox 93+, Safari 16+) all support AVIF now, so basically no need to worry.

Practical Configuration Examples

Combining these configurations, here’s how to write for different scenarios:

Homepage Hero Image (Priority loading, high quality)

<div style={{ position: 'relative', width: '100%', height: '60vh' }}>
  <Image
    src="/hero.jpg"
    fill
    priority
    quality={90}
    sizes="100vw"
    style={{ objectFit: 'cover' }}
    alt="Welcome to our site"
  />
</div>

Article List Thumbnails (Lazy loading, medium quality)

{posts.map(post => (
  <Image
    key={post.id}
    src={post.thumbnail}
    width={300}
    height={200}
    quality={75}
    alt={post.title}
  />
))}

Footer Related Link Icons (Lazy loading, low quality)

<Image
  src="/footer-icon.png"
  width={40}
  height={40}
  quality={60}
  alt="Footer icon"
/>

Common Errors and Solutions

Having covered so much usage, let’s now discuss the most common pitfalls in actual development. I’ve encountered all these errors myself, and some took quite a while to figure out.

Error 1: Un-configured Host

This error appears most frequently.

Error message:

Error: Invalid src prop (https://example.com/image.jpg) on `next/image`, 
hostname "example.com" is not configured under images in your `next.config.js`

Cause:
You used an external URL in the Image component but didn’t configure remotePatterns to allow this domain in next.config.js.

Solution:
Add configuration to next.config.js:

module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
        port: '',
        pathname: '/**',
      },
    ],
  },
}

Important notes:

  1. Must restart dev server after changing config file (npm run dev)
  2. hostname must match exactly, can’t use wildcards. *.example.com doesn’t work, must write specific subdomain
  3. If your images come from multiple domains, add more objects to the remotePatterns array

Error 2: Layout Shift / High CLS

Symptom:
During page loading, image area suddenly appears, pushing other content down, page jumps around.

Cause:
Two possibilities:

  1. Didn’t set width and height, browser doesn’t know how much space to reserve
  2. Used fill attribute, but parent container didn’t set height

Solution:

Case 1: Set clear width and height for images

// ❌ Wrong: Missing width and height
<Image src="/product.jpg" alt="Product" />

// ✅ Correct: Specify width and height
<Image src="/product.jpg" width={400} height={300} alt="Product" />

Case 2: Set height for parent container

// ❌ Wrong: Parent container has no height
<div style={{ position: 'relative', width: '100%' }}>
  <Image src="/hero.jpg" fill alt="Hero" />
</div>

// ✅ Correct: Parent container has explicit height
<div style={{ position: 'relative', width: '100%', height: '400px' }}>
  <Image src="/hero.jpg" fill alt="Hero" />
</div>

Error 3: Images Appear Blurry or Oversized

Symptom:
When accessed on mobile, images are either blurry or load slowly.

Cause:
Didn’t configure sizes attribute, Next.js doesn’t know what size images to generate, so used default value 100vw (entire viewport width). If your image actually only occupies half the screen, it generated an image twice as large as needed.

Solution:
Configure sizes according to actual render size:

// Image occupies different widths on different screens
<Image
  src="/product.jpg"
  width={400}
  height={300}
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
  alt="Product"
/>

If your image is always fixed width (like thumbnails), just use width and height, no need for sizes.

Error 4: Using Deprecated APIs

Next.js 14 and 15 have some API changes. If you’re following old tutorials, you might use already deprecated syntax.

Deprecated 1: domains configuration

// ❌ Deprecated in Next.js 14+
module.exports = {
  images: {
    domains: ['example.com'],
  },
}

// ✅ Switch to remotePatterns
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
      },
    ],
  },
}

Deprecated 2: onLoadingComplete callback

// ❌ Deprecated in Next.js 14+
<Image
  src="/image.jpg"
  width={400}
  height={300}
  onLoadingComplete={() => console.log('loaded')}
  alt="Image"
/>

// ✅ Switch to onLoad
<Image
  src="/image.jpg"
  width={400}
  height={300}
  onLoad={() => console.log('loaded')}
  alt="Image"
/>

Next.js 16 changes (coming soon):

// ⚠️ In Next.js 16, priority changes to preload
// Old syntax (Next.js 15 and earlier)
<Image src="/hero.jpg" width={1920} height={1080} priority alt="Hero" />

// New syntax (Next.js 16)
<Image src="/hero.jpg" width={1920} height={1080} preload alt="Hero" />
// Or
<Image src="/hero.jpg" width={1920} height={1080} loading="eager" fetchPriority="high" alt="Hero" />

Quick Troubleshooting Checklist

When encountering problems, check in this order:

  1. ✅ Are remote images configured with remotePatterns?
  2. ✅ Did you restart dev server after modifying config file?
  3. ✅ Are images set with width and height (or parent container set with height)?
  4. ✅ When using fill, does parent container have position: relative and explicit height?
  5. ✅ Are responsive images configured with reasonable sizes?
  6. ✅ Are you using deprecated APIs (domains, onLoadingComplete, etc.)?

Advanced Techniques and Best Practices

Having mastered basic usage and common error handling, let’s look at some advanced techniques that can take your image experience to the next level.

Using placeholder to Improve Experience

Image loading takes time, especially with slow networks. If you can show a blurry placeholder first, user experience improves significantly.

blur placeholder

import Image from 'next/image'
import heroImage from '/public/hero.jpg'

export default function Hero() {
  return (
    <Image
      src={heroImage}
      placeholder="blur"
      alt="Hero image"
    />
  )
}

For locally imported images, Next.js automatically generates a low-quality base64 placeholder. Adding placeholder="blur", images first show a blurry version during loading, then gradually become clear. This effect is common on sites like Instagram and Medium.

blur placeholder for remote images

Remote images require you to manually provide blurDataURL:

<Image
  src="https://example.com/image.jpg"
  width={800}
  height={600}
  placeholder="blur"
  blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
  alt="Remote image"
/>

You can use this online tool to generate blurDataURL, or generate it server-side with the sharp library.

empty placeholder

If you don’t need placeholder effect, you can explicitly set placeholder="empty"—the image area is blank before loading. This is the default behavior, same as not writing it.

Using with CDN

Next.js defaults to using its own Image Optimization API to optimize images. If you’re using image CDN services like Cloudinary or Uploadcare, you can configure custom loaders.

// next.config.js
module.exports = {
  images: {
    loader: 'cloudinary',
    path: 'https://res.cloudinary.com/your-cloud-name/',
  },
}

Or write your own loader function:

// next.config.js
module.exports = {
  images: {
    loader: 'custom',
    loaderFile: './my-loader.js',
  },
}

// my-loader.js
export default function myLoader({ src, width, quality }) {
  return `https://cdn.example.com/${src}?w=${width}&q=${quality || 75}`
}

This way all image requests go through your CDN instead of the Next.js server. Suitable for high-traffic websites.

Complete Responsive Image Solution

Responsive images aren’t just about resizing—you also need to consider display approaches for different scenarios.

Differentiated strategy for mobile, tablet, desktop

<div className="image-container">
  <Image
    src="/product.jpg"
    width={1200}
    height={800}
    sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
    style={{
      width: '100%',
      height: 'auto',
    }}
    alt="Product image"
  />
</div>

Paired with CSS:

.image-container {
  width: 100%;
}

@media (min-width: 640px) {
  .image-container {
    width: 50%;
  }
}

@media (min-width: 1024px) {
  .image-container {
    width: 33.333%;
  }
}

When the sizes attribute and CSS media queries stay consistent, browsers can select the most appropriate image size.

Monitoring and Debugging

Chrome DevTools to view image loading

Open Chrome DevTools → Network tab → Check Img filter, you can see for each image:

  • File size
  • Loading time
  • Response headers (including format info)

You’ll notice that images using the Image component have URLs with parameters like ?w=xxx&q=xxx—that’s Next.js doing optimization.

Lighthouse performance testing

Chrome DevTools → Lighthouse → Click “Analyze page load”, focus on these metrics:

  • LCP (Largest Contentful Paint): Ideal value < 2.5 seconds
  • CLS (Cumulative Layout Shift): Ideal value < 0.1
  • Image element suggestions: Lighthouse will tell you which images aren’t well optimized

Every time I finish image optimization, I run Lighthouse to see how much the performance score improves. Usually can go from 60-something to 90+.

Continuously monitor Core Web Vitals

For production environments, it’s recommended to use Google Search Console or Vercel Analytics to continuously monitor Core Web Vitals metrics. This way you can promptly discover performance regression issues.

Conclusion

After all that, the Next.js Image component’s core is really about solving three problems: slow image loading, configuration errors, layout shifts.

Use the Image component correctly, and you get:

  • 60-80% image size reduction (automatic WebP/AVIF conversion)
  • LCP maintained under 2.5 seconds (reasonable use of priority)
  • CLS close to zero (correctly setting width/height or fill)

Key configurations to remember:

  1. Configure remotePatterns for remote images, restart server after changes
  2. Set width and height, or use fill with parent container height
  3. Add priority to critical above-the-fold images, other images default lazy loading is fine
  4. Configure sizes for responsive images, let browser choose appropriate size
  5. Adjust quality based on image importance: above-the-fold 90, general 75, thumbnails 60

Go check your project now and replace those <img> tags with <Image>. Run Lighthouse once and see how much the performance improves. I bet it’ll go up at least 20 points.

FAQ

Why do remote images throw 'Un-configured Host' error?
Next.js Image component requires explicit configuration of allowed remote image domains for security.

Add domain configuration in next.config.js's images.remotePatterns, including protocol, hostname, and optional pathname.

After configuration, you must restart the dev server for it to take effect.
Must I set width and height for Image component?
Yes, you must set them. This is to avoid layout shift (CLS).

If you don't want fixed dimensions, you can:
• Use fill mode with parent container dimensions
• Use aspect-ratio to maintain proportions

Not setting them will worsen CLS score.
How do I avoid layout shift when images load?
Methods:
1) Set width and height
2) Use fill mode with parent container
3) Use placeholder="blur" to show blur placeholder
4) Use aspect-ratio to maintain proportions

Key is ensuring image container has explicit dimensions.
When should I use priority property?
priority is for above-the-fold critical images (Hero images, logos, etc.), telling Next.js these images need immediate loading, don't lazy load.

Usually for first-screen visible important images. Don't overuse, otherwise performance will degrade.
Does Image component automatically convert image formats?
Yes. Next.js Image component automatically converts images to WebP format (if browser supports), and browsers supporting AVIF will prioritize AVIF.

This can significantly reduce image sizes (usually 60-80%), improving load speed.
What's the purpose of sizes property?
sizes tells the browser what image size is needed at different screen sizes, and the browser automatically selects the most appropriate image size based on this info and srcset.

This is very important for responsive image optimization, avoiding mobile devices loading oversized images.
How do I optimize image quality?
Use quality property to control image quality:
• Above-the-fold critical images: 90
• General images: 75
• Thumbnails: 60

Higher quality means larger files—need to balance. You can also use different image sizes: large for desktop, small for mobile.

If you run into issues, come back and check the common errors section of this article—you’ll find answers to most problems. While the Next.js Image component has many configuration options, mastering the core few will handle most scenarios.

16 min read · Published on: Dec 19, 2025 · Modified on: Jan 22, 2026

Comments

Sign in with GitHub to leave a comment

Related Posts