Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Fix blurry or overly compressed images in Next.js by working in this order: verify the original asset, compare its pixels with the rendered size and device density, confirm the browser selected a large enough responsive candidate, then tune output quality and format. The quality prop can change compression, but it cannot restore detail that is missing from the source.

Start with the image that Next.js is actually delivering

An image that looks soft may have several different causes. The source file may already be small or compressed, the browser may have selected an undersized srcset candidate, CSS may be enlarging the image, or the optimizer may be using a format or quality setting that trades away detail. Diagnose those separately instead of immediately setting every image to quality 100.

Inspect the original asset

Open the source at its natural pixel dimensions before changing application code. If it is soft, noisy, or heavily compressed there, no Next.js setting can recreate lost detail. Replace it with a larger, cleaner original, or redesign the component so the image is displayed smaller. Increasing output quality for a poor original only creates a larger file without making it sharper, as the Next.js Image API reference warns.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not enlarge beyond available pixels

A raster image contains a finite grid of pixels. Displaying it substantially larger forces the browser to estimate intermediate pixels, which produces blur. Compare the source’s intrinsic width and height with the CSS-rendered dimensions, including the device-pixel ratio (DPR). A 400-pixel-wide source displayed at 400 CSS pixels may need roughly 800 physical pixels on a DPR-2 screen for a crisp result. If the source cannot provide that detail, obtain a larger version or reduce its rendered size.

#1 Best Overall
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Understand what width, height, fill and sizes do

Intrinsic dimensions are not display dimensions

For local and remote images, provide accurate intrinsic width and height, or use fill when the image should occupy a positioned parent. These values establish aspect ratio and reserve space, preventing layout shift; they do not dictate the final CSS size. Set the rendered dimensions with CSS, a layout utility, or the parent layout.

import Image from 'next/image';

export default function Card({ src, alt }) {
  return (
    <div className="card-media">
      <Image
        src={src}
        alt={alt}
        width={1200}
        height={800}
        sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"
        style={{ width: '100%', height: 'auto' }}
      />
    </div>
  );
}

The numbers above must match the file’s real intrinsic dimensions; they are not a request to resize the browser box. The sizes expression is an example for a three-column desktop layout, two-column tablet layout, and full-width mobile layout. Measure your actual grid and change the expression when the design changes.

Use fill for parent-sized media

<div className="hero">
  <Image
    src="/hero.jpg"
    alt=""
    fill
    sizes="100vw"
    style={{ objectFit: 'cover' }}
  />
</div>

The parent must establish a positioning context (for example, position: relative) and a height or aspect ratio. With fill, the parent’s dimensions determine the rendered box; sizes still tells the browser how wide the image will be so it can choose an appropriate candidate.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Make responsive candidates match the real layout

Next.js emits responsive srcset candidates. The browser combines those candidates with your sizes hint, viewport width, and DPR to select one resource. If sizes is missing for an image that is not full viewport width, the browser can request an unsuitable candidate—often too small, which appears blurry, or unnecessarily large, which wastes bandwidth.

Write a layout-accurate expression

  • Full-width image: use sizes="100vw" when it genuinely spans the viewport.
  • Constrained content: describe the maximum content width, such as sizes="(min-width: 1200px) 900px, 100vw" if the image is 900 CSS pixels wide on large screens.
  • Grid card: include breakpoints that mirror the number of columns, for example one-third of the viewport on desktop and full width on mobile.

Do not copy an example blindly. Inspect the deployed page at each breakpoint and ensure the expression describes the image’s expected rendered width, not its source file width.

Rank #2
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

Verify the browser’s choice

In browser developer tools, inspect the image element and its currentSrc. Compare that URL’s natural pixel dimensions with the element’s rendered dimensions and DPR. In the Network panel, check whether the response is an optimizer URL or an original source URL, and inspect the actual response format. The web.dev responsive-images guidance explains how srcset and sizes interact; the deployed page, rather than JSX alone, is the source of truth.

Tune the quality prop deliberately

Next.js documents quality as an integer from 1 through 100, with 75 as the documented default. Higher values generally preserve more fidelity and produce larger files; lower values reduce transfer size and can introduce blur, ringing, or blockiness. There is no universally best number. Compare representative images at their actual display size and record both visual results and transfer bytes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configure quality in current Next.js versions

Starting with Next.js 16, images.qualities is an allowlist. A component value outside that list is mapped to the closest allowed value, while a direct Image Optimization API request using an unconfigured quality returns HTTP 400. Check the documentation for the Next.js version installed in your project before changing configuration.

// next.config.js
const nextConfig = {
  images: {
    qualities: [60, 75, 85],
  },
};

module.exports = nextConfig;

Choose a small, intentional set rather than exposing arbitrary values. Keep photographic hero images and small thumbnails under separate policies only when your visual and bandwidth requirements justify it.

Evaluate quality at the right scale

A compressed image can look acceptable when zoomed out and poor at its actual UI size. Test fine edges, text inside images, gradients, skin tones, and dark detail. Also test on a DPR-2 display: an image that appears crisp on a low-density monitor may reveal undersampling on a high-density screen.

Choose formats without assuming smaller means sharper

Next.js can negotiate configured formats using the request’s Accept header. WebP is the documented default configured format, and AVIF can be added. If multiple configured formats match, their array order determines which is selected. If none matches—or if the source is animated—the optimizer falls back to the original source format.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
// next.config.js
const nextConfig = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
};

module.exports = nextConfig;

AVIF may require more cached variants than a single format. WebP and AVIF often compress more efficiently than JPEG or PNG, but file size alone does not establish visual quality. Compare each format for the actual asset, especially when it contains fine lines, text, gradients, transparency, or animation. Keep browser support and fallback behavior in your deployment requirements.

When unoptimized is appropriate

The API identifies unoptimized as useful for SVG, animated GIF, and very small images that do not benefit from transformation. It serves the source without changing its quality, size, or format. This is not a general fix for blurry photographs: it simply removes the optimizer from the path.

Configure remote images safely

Next.js cannot inspect a remote file at build time. Supply its dimensions (and optional blur data) manually, or use fill for a parent-sized layout. Restrict hosts and paths with a narrowly specified remotePatterns entry rather than allowing an entire domain unnecessarily.

// next.config.js
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.example.com',
        pathname: '/catalog/**',
      },
    ],
  },
};

module.exports = nextConfig;

The built-in optimizer does not forward authentication headers when fetching a source. If the image requires authentication, use a delivery arrangement that exposes an authorized, cacheable image URL, or consider disabling optimization for that source. Do not put a secret token in a public image URL.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a custom loader when a CDN already transforms images

If your CMS or image CDN already performs resizing and format negotiation, a custom loader can generate its URLs instead of sending the file through the default optimizer. Next.js documents this as an architectural option, not a requirement for ordinary sites. Define how width, quality, crop, and format parameters map to that service, then verify the generated URL and cache behavior in production.

A repeatable debugging checklist

  1. Open the original: check natural pixels and compression before any Next.js setting.
  2. Measure the box: record CSS width and height at every responsive breakpoint.
  3. Account for DPR: ensure the selected candidate has enough physical pixels for the display density.
  4. Inspect currentSrc: confirm the browser chose an appropriate srcset candidate.
  5. Check sizes: make its values match the actual layout.
  6. Inspect response details: verify format, optimizer URL, status, and transfer size.
  7. Test quality values: compare a small allowlisted set at the real display size.
  8. Check special cases: animation, SVG, transparency, remote authentication, and CDN transformations.

Common symptoms, causes and fixes

Symptom Likely cause Fix
Blurry on every device Original is too small or already soft Replace the source or render it smaller; quality cannot restore detail.
Sharp on desktop, soft on mobile Incorrect sizes or an undersized mobile candidate Match sizes to mobile layout and inspect currentSrc.
Sharp on low-DPR screen, soft on Retina Candidate lacks enough physical pixels Verify DPR-aware selection and provide larger source dimensions.
Image shifted while loading Missing or inaccurate intrinsic dimensions Set correct width/height, or establish a sized parent for fill.
HTTP 400 after changing quality Quality is not in the Next.js 16 allowlist Add it to images.qualities or use an allowed value.
Remote image fails to optimize Host/path is not allowed or source needs authentication headers Narrowly configure remotePatterns; provide a public authorized URL or use an alternative delivery path.
AVIF appears different or cache grows Format negotiation and additional variants Compare AVIF with WebP for the asset and account for extra cache variants.

Performance and operating-cost trade-offs

Image quality is a three-way decision among visual fidelity, rendered width/DPR coverage, and transfer size. Larger originals and higher quality increase bytes; undersized candidates save bytes but blur; AVIF may reduce bytes while adding encoding or cache complexity. Measure a representative set rather than optimizing a single unusually simple image.

For each image class, document the maximum rendered width, expected DPR, acceptable visual artifacts, and target byte budget. Recheck after changing breakpoints, card counts, or typography: a layout change can invalidate sizes even when the JSX still compiles.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your task is to capture a rendered page rather than debug the Next.js pipeline, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. Before capture it accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP tools—take_screenshot, get_page_info, and capture_pdf—work with Claude, Cursor, and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for authentication and options. The service supports full-page and CSS-selector captures, dark mode, device presets or custom viewports, retina scale, PDF paper settings, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous jobs with webhooks, bulk capture of up to 100 URLs per call, usage data, and an OpenAPI specification.

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Every feature is included on every plan: 1,000 screenshots per month free with no card, then Starter is $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000; yearly billing provides two months free. Create a free ScreenshotNeo account to start with 1,000 screenshots and no card.

Best Value
Sale
JavaScript and jQuery: Interactive Front-End Web Development
  • JavaScript Jquery
  • Introduces core programming concepts in JavaScript and jQuery
  • Uses clear descriptions, inspiring examples, and easy-to-follow diagrams

FAQ

Does setting quality={100} guarantee a sharper image?

No. It only changes optimization output. Source detail and a correctly sized responsive candidate come first.

Should every image use sizes="100vw"?

Only images that actually span the viewport. For cards and constrained content, describe their real width at each breakpoint.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can Next.js optimize an authenticated remote image?

Not through the built-in optimizer’s fetch, which does not forward authentication headers. Use an authorized public delivery URL, a suitable custom arrangement, or another delivery path.

Frequently Asked Questions

Does setting quality={100} guarantee a sharper image?

No. It changes optimization output but cannot restore detail missing from the source or an undersized responsive candidate.

Should every image use sizes=”100vw”?

Only images that truly span the viewport; constrained layouts need values matching their actual width at each breakpoint.

Can Next.js optimize an authenticated remote image?

The built-in optimizer does not forward authentication headers, so use an authorized delivery arrangement or another optimization path.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Quick Recap

SaleBestseller No. 1
HTML and CSS: Design and Build Websites
HTML and CSS: Design and Build Websites
HTML CSS Design and Build Web Sites; Comes with secure packaging; It can be a gift option
$15.74
SaleBestseller No. 2
Web Design with HTML, CSS, JavaScript and jQuery Set
Web Design with HTML, CSS, JavaScript and jQuery Set
Brand: Wiley; Set of 2 Volumes
$35.05
SaleBestseller No. 3
SaleBestseller No. 5
JavaScript and jQuery: Interactive Front-End Web Development
JavaScript and jQuery: Interactive Front-End Web Development
JavaScript Jquery; Introduces core programming concepts in JavaScript and jQuery; Uses clear descriptions, inspiring examples, and easy-to-follow diagrams
$24.90

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.