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.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsDo 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
- 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.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →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
- 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.
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.
Rank #3
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.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →// 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.
Rank #4
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
- Open the original: check natural pixels and compression before any Next.js setting.
- Measure the box: record CSS width and height at every responsive breakpoint.
- Account for DPR: ensure the selected candidate has enough physical pixels for the display density.
- Inspect
currentSrc: confirm the browser chose an appropriatesrcsetcandidate. - Check
sizes: make its values match the actual layout. - Inspect response details: verify format, optimizer URL, status, and transfer size.
- Test quality values: compare a small allowlisted set at the real display size.
- 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.
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.
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
- 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.
Recommended Free Tools
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.
Quick Recap
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.

