Next.js Responsive Images: How `srcset`, `sizes`, and `/_next/image` Turn One Upload Into the Right File for Each Screen

What those many URLs in DevTools mean, what the browser actually downloads, and when a plain `<img>` is enough.

Published on

Share:

You drop a single PNG into your project—maybe a hero photo or a blog screenshot—and everything looks normal in your code. Then you open Chrome DevTools, click the image, and suddenly there is a long list of URLs. It feels like Next.js duplicated your file. It did not. The framework is setting up responsive image delivery: one source file, many possible optimized versions, and rules that let the browser pick the smallest file that still looks sharp on that screen.

This guide explains that machinery in plain language—no React wizardry required. If you are still piecing together how a modern site is built, our React, Next.js, and App Router overview maps what JavaScript, React, Next.js, and URL routing each handle on a typical Next.js site—the broader stack your pages (and this image behavior) run on.

Scope note

Written for modern Next.js sites using the next/image component. Exact width steps, default quality, and supported output formats can vary slightly by Next.js version and next.config.js; use DevTools on your own project to confirm the URLs you see.

You uploaded one file—why does Inspect Element show so many URLs?

In your editor and in Git, you still have one image file—say /public/blog/hero.png. What changes is the HTML that Next.js emits at runtime. The Image component automatically adds a srcset attribute: a list of candidate image addresses at different widths (and often a separate src fallback). Each candidate typically points at the Image Optimization API path—by default /_next/image—with query parameters such as url, w (width), and q (quality).

Your file vs. the markup the component outputs

Think of your upload as the master print. The srcset list is a menu of smaller prints the browser may order—640 pixels wide, 750 wide, and so on—not a stack of files you must maintain by hand. Next.js generates those optimized variants when a given size is requested (and can reuse cached results afterward, similar in spirit to how HTTP caching keeps repeat visits fast).

Elements panel vs. Network panel

This distinction saves a lot of confusion. The Elements tab shows the full srcset menu baked into the page. The Network tab shows what actually traveled over the wire—usually one image request for that slot (plus, sometimes, a tiny blur placeholder). Seeing ten URLs in markup does not mean ten downloads on first paint.

What DevTools is showing you
Where you lookWhat you seeWhat it means
Elements → <img> attributesLong srcset, src, sizes, altAll options the browser may choose from
Network → Img filterOften one /_next/image?... requestThe variant actually downloaded for this viewport
Your /public or import folderOne original fileWhat you authored; the rest is generated on demand
DevTools: markup vs. networkLeft panel lists many srcset candidate URLs in HTML; right panel shows a single downloaded image request in the Network tab.Same image: many URLs in markup, one downloadElementssrcset:.../image?w=640.../image?w=750.../image?w=828+ more candidates…Network1 request ✓picked for this screen

What is srcset?

srcset is a standard HTML feature (not unique to Next.js) that tells the browser: "here are several versions of this image at different widths—pick the best one." Each entry pairs a URL with a width descriptor such as 640w (640 CSS pixels wide). The MDN img reference documents the syntax; Next.js fills it in for you when you use next/image.

A menu of sizes, not a pile of downloads

Without responsive images, every visitor—phone, tablet, or ultrawide monitor—might download the same 2 MB file. With srcset, the browser can request a tighter crop of bytes when the image only displays at 400 pixels on screen. That is the core web performance win, and it is why blog heroes and product shots on modern sites rarely use a naked <img src="huge.jpg"> anymore.

One upload, many srcset candidatesA single hero.png file in the project connects to multiple /_next/image URLs at different widths listed in srcset.One file in your repo → many options in srcsethero.png(your upload)srcset menu (in HTML)/_next/image?...&w=640&q=75/_next/image?...&w=750&q=75/_next/image?...&w=1080&q=75browser picks one →

What does the sizes attribute do?

If srcset is the menu, sizes is the note you leave for the browser: "on a phone this image will be about X pixels wide; on a desktop, about Y." Without that hint, the browser may assume the image spans the full viewport width (100vw) and download a larger file than necessary—wasting bandwidth and slowing how fast the page feels.

The hint most sites get wrong

Next.js documentation is explicit: use sizes when the image is responsive—especially with the fill prop or CSS that stretches it. A typical blog hero might use something like (max-width: 1024px) 100vw, 42rem, meaning "on narrow screens, treat it as full width; otherwise cap around 42 rem." When sizes is missing on a responsive layout, Next.js may generate a simpler density-based srcset (1x, 2x) instead of the full width ladder—fine for fixed icons, wrong for fluid heroes.

The web.dev responsive images guide walks through how to read and write sizes expressions; the math is easier than it looks once you match them to your real CSS layout.

sizes guides srcset choiceThe sizes attribute tells the browser how wide the image displays; the browser then selects the matching entry from srcset.sizes tells the browser how wide the image displayssizeslayout hintsrcsetwidth options1 pickPhone: image ≈ 360px wideDesktop: image ≈ 672px wideWrong sizes → wrong file → wasted bytes or blurry image

📱 The Retina Screen Factor: Device Pixel Ratio (DPR) Math

You might write a perfect sizes hint telling the browser that an image slot is exactly 360px wide on mobile. But when you inspect the Network panel on an iPhone, you see it downloading a 1080w file.

Modern high-density displays use a multiplier called Device Pixel Ratio (DPR). An iPhone or high-end desktop monitor has a DPR of 2x or 3x, meaning it squeezes multiple physical screen pixels into a single layout CSS pixel to keep text and graphics sharp. The browser automatically handles the math behind the scenes:

360px (Layout Width) × 3 (DPR Multiplier) = 1,080px (Target Physical Resolution)

Armed with that target, the browser skips the lower 360w candidate and grabs the closest match to 1080w in your srcset ladder. Your layout hint is working exactly as it should—it just factors in screen density so the final image does not look blurry.

What is /_next/image?

When you see long image addresses in DevTools, they often start with /_next/image. That is not a folder of extra files sitting next to your PNG in /public. It is a built-in route on your Next.js site—an image optimization endpoint that prepares the right version of your picture when a visitor's browser asks for it.

Everyday analogy: the neighborhood kitchen

Picture a small restaurant with one pot of soup in the kitchen—that is your one image file. The menu only offers cup, bowl, or bread bowl (those are the widths in srcset). The server checks whether you are at the counter or a booth (sizes), so the kitchen knows how big a portion to serve. When you order, the cook ladles out just that size. That step is /_next/image: same soup, portioned for you. If someone else orders the same bowl right after, the cook may reuse one already plated—that is caching. The kitchen did not make twenty pots at opening; it responds order by order.

How to read the URL in plain English

A typical optimized address looks like this:

/_next/image?url=%2Fimages%2Fhero.png&w=750&q=75

  • url — which source image to use (often a path under /public, URL-encoded in the query string).
  • w — target width in pixels for this request (the size entry the browser chose from srcset).
  • q — compression quality (commonly around 75 by default; higher means larger files).

The server reads your original file, resizes and compresses it to match those parameters, and may serve a modern format such as WebP or AVIF when the browser supports it. The response can be cached so the next visitor who needs the same width does not pay the full processing cost again—similar to how a CDN or browser cache reuses work, as described in our HTTP caching guide.

What it is not

/_next/image is not a duplicate upload and not something you edit by hand. You do not commit dozens of variants to Git. You keep one source asset; Next.js generates derivatives on demand (or from cache) when each srcset URL is requested. If you need the raw file with no optimizer in the middle—static export quirks, special hosting, or a fixed asset that must never change—use the unoptimized prop on next/image or adjust image settings in next.config.js. The default path can also be renamed via the images.path config if your host requires it—see the Next.js Image documentation for details.

What the next/image component adds on top

The React Image component is what wires your file into that pipeline: it outputs the srcset, sizes, and /_next/image URLs so you do not hand-write them. It also handles concerns HTML alone does not solve well out of the box.

Width ladders, quality, and config

You can customize which widths appear via deviceSizes and imageSizes in next.config.js. Typical defaults include common viewport breakpoints (640, 750, 828, 1080, and up) plus smaller steps for thumbnails.

The Rendered HTML Output

Swipe horizontally or scroll to the right to view the full screenshot.

A code snippet from Chrome DevTools showing the rendered HTML img tag with a comprehensive srcset width ladder and sizes attribute generated by the Next.js Image component.
Example of a rendered HTML output: This is what the browser actually receives after Next.js automatically generates the full srcset width ladder and computed sizes attribute based on your project configuration.

The component also encourages layout stability. Set explicit width and height, or use fill inside a parent that already has a defined size, so the browser holds space before the file loads and surrounding text does not jump. next/image requires an alt value: describe what the picture communicates (not the filename), so assistive technology and search engines get useful context. Images also sit inside a larger page layout—our semantic HTML, landmarks, and ARIA guide explains how to structure regions and navigation so screen reader users can reach your content without wading through every link first. For a hero that is likely the largest thing on first paint, add priority or preload so default lazy loading does not delay it.

Is this actually faster? Tradeoffs to know

For most content sites—blogs, marketing pages, documentation—responsive optimized images are a net win. Mobile users download fewer bytes; desktops still get crisp assets; and you avoid manually exporting six PNG sizes every time you swap a screenshot. That lines up with why teams measure delivery costs in tools like our cloud egress calculator and CDN ROI calculator: smaller payloads mean less transfer spend over time.

Wins, costs, and when a plain <img> is enough

Wins: right-sized downloads, automatic modern formats, lazy loading by default, and less layout shift when dimensions are set correctly. Costs: the first request for a given width may wait on server-side processing; misconfigured sizes can still waste bandwidth; and very large source files remain a bad starting point—optimization cannot invent detail from a tiny upload stretched huge. Plain <img>: fine for decorative icons, SVGs, email templates, or assets that must never pass through an optimizer. For photos and screenshots that affect load speed, next/image is usually the better default.

If you are validating visual quality as well as bytes, pair this workflow with our WCAG contrast guide and the WCAG color contrast solver so images stay readable—not just lightweight.

Definitive Summary

  • You still author one image file; Next.js emits a srcset menu of URLs. /_next/image is the on-demand optimizer route—not extra files in your repo.
  • Elements lists every candidate; Network shows what was actually downloaded—typically one request per image slot.
  • sizes tells the browser how wide the image displays; wrong values cause oversized downloads or soft images.
  • The optimizer resizes, compresses, and can serve modern formats; set unoptimized when you need the raw file end-to-end.
  • Use meaningful alt text, correct dimensions, and priority or preload for hero images; reach for plain <img> only when optimization is not appropriate.

Shaleen Shah is the Founder and Technical Product Manager of Definitive Calc™. He is also a Sr. Analyst of SEO Operations at JD Power, specializing in systems and data behind modern search and information discovery.

Driven by technical rigor, Shaleen breaks down the practical math of daily life, from homeownership nuances to long-term wealth building. He blends a decade of investing experience with a privacy-first, stateless architecture, ensuring every high-performance calculator replaces uncertainty with mathematical precision.

Continue Reading

Explore more insights on web development, cloud, and network architecture

Web & NetworkFinance

May 24, 2026

What Software Technical Debt Costs in Developer Hours (And Why It Grows Over Time)

Software technical debt is the ongoing developer time a web or app codebase needs for fixes, updates, and upkeep. Learn how those hours add up over time, why the load can increase year to year, and how to model the cost for your team.

Read article
Web & Network

May 20, 2026

Cookies, localStorage, and sessionStorage: What Gets Saved in Your Browser, How Long It Lasts, and Why a Cookie Banner Is Not the Whole Story

Websites stash data in more places than cookies. Learn how cookies, localStorage, and sessionStorage differ, what survives when you close a tab, and why consent banners often leave other storage alone.

Read article
Web & Network

May 17, 2026

Semantic HTML, Landmarks, and ARIA: What They Are and Why Accessibility Needs Them

Semantic tags, landmarks, and ARIA help structure a page so screen readers can jump to the right areas. This straightforward guide explains each piece, how they work together, and what to improve so your site is easier for everyone to use.

Read article
Web & Network

April 16, 2026

React, JavaScript, Next.js, and the App Router: Where Each Fits

A non-technical map of how JavaScript, React, Next.js, and the App Router work together so modern websites feel fast, stay interactive, and stay searchable.

Read article
Web & Network

March 28, 2026

Stop Treating WCAG Contrast Like a Slider Guessing Game

WCAG AA and AAA contrast checks with exact hex codes—no trial-and-error loop.

Read article
Web & Network

March 26, 2026

Script Loading Strategy: beforeInteractive vs. afterInteractive

Choose the right script timing strategy for product performance. Compare beforeInteractive and afterInteractive, see Core Web Vitals impact, and scale script governance across large websites.

Read article

The information in this article is for educational and informational purposes only and does not constitute professional, technical, or architectural advice. Definitive Calc is not liable for any outcomes related to your use or application of the concepts discussed.