To predict a responsive image candidate, resolve sizes to a CSS width, multiply by device pixel ratio, and compare that target with srcset. Then verify the selected URL: browsers retain discretion over the final choice.

This walkthrough is for someone checking an authored web page in Chrome on a Mac. You will calculate likely candidates, test a local page containing original abstract shapes, and distinguish a misleading size declaration from normal browser selection behavior.

What do sizes, srcset, and DPR each tell the browser?

With width descriptors, srcset lists the available resources and their intrinsic pixel widths. A descriptor such as 800w must describe an image that is actually 800 pixels wide. Keep width descriptors and density descriptors such as 2x in separate source sets; mixing them in one srcset is invalid. MDN’s image element reference documents these requirements.

sizes supplies the intended display width for resource selection. The browser evaluates its conditions in order and uses the first matching entry. Put the unconditional fallback last. Source sizes accept lengths such as 480px, 50vw, and calc(100vw - 32px); percentage values such as 50% are not valid slot widths. Using responsive images in HTML

CSS controls the displayed dimensions. Treat your CSS and explicit sizes list as two descriptions that you must keep aligned: one determines layout, while the other informs resource selection. Changing sizes alone does not implement the corresponding layout. HTML Standard: Sizes attributes

DPR describes the relationship between physical pixels and CSS pixels. Read window.devicePixelRatio instead of assuming a value from the Mac model or display name. Page zoom can change this value, and moving a window between displays can change it too. Pinch zoom does not change DPR. MDN: Window.devicePixelRatio

How do you calculate the likely candidate?

For a resolved source size S, resource width W, and DPR D, use these two equivalent calculations:

Target resource width = S × D
Candidate effective density = W ÷ S

The HTML processing model normalizes width descriptors by dividing each candidate width by the source size. MDN also explains the practical prediction as multiplying the size hint by DPR. HTML Standard: Normalizing the source densities, MDN: HTMLImageElement.sizes

For a useful working estimate, choose the smallest candidate at or above the target width. If every candidate falls below the target, identify the largest available one and record the shortfall. This is an explicit prediction rule for the exercises below. The HTML standard leaves the final selection implementation-defined; it does not require every browser to follow this rounding rule. HTML Standard: Selecting an image source

Consider this source-size list, paired with candidates of 480w, 800w, 1200w, and 1440w:

(max-width: 600px) calc(100vw - 32px),
(max-width: 1200px) calc(50vw - 32px),
568px

100vw represents the viewport width and 50vw represents half that width. These units refer to the viewport, rather than the image’s parent container. CSS Values and Units: Viewport-percentage lengths

The following table contains illustrative calculations, not recorded browser results. The final column applies the stated prediction rule.

Viewport width, CSS px DPR Resolved source size, CSS px Target resource width, px Predicted candidate
600 1 568 568 800w
600 2 568 1,136 1200w
601 2 268.5 537 800w
1,000 1 468 468 480w
1,000 2 468 936 1200w
1,400 2 568 1,136 1200w
1,400 3 568 1,704 1440w, below target

The transition from 600 to 601 CSS pixels is especially useful to test. At 600, the first condition supplies a nearly full-width slot. At 601, the second condition supplies a much narrower slot. A wider viewport therefore produces a smaller target image. That follows directly from this authored layout contract.

At a 1,000-pixel viewport and DPR 2, the source size is 468 CSS pixels. The four candidates have effective densities of approximately 1.03x, 1.71x, 2.56x, and 3.08x. The 1200w candidate is the first to exceed the target density of 2x under our prediction rule.

How can you build a complete local test?

Use a Mac with Chrome and Python 3.8 or newer installed. Save the following complete program as responsive_demo.py in a plain-text editor. It generates four PNG files containing the same rectangle and circle, writes a matching page, and starts a local server. All generated files go into a new temporary directory, so existing files are not overwritten.

The page deliberately uses an eager image and explicit source sizes. Its CSS widths match the three branches used in the calculation table. The server uses Python’s documented ThreadingHTTPServer and directory-based request handler. Python: http.server

from functools import partial
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
import struct
import tempfile
import zlib


def chunk(kind, data):
    return (
        struct.pack("!I", len(data)) + kind + data
        + struct.pack("!I", zlib.crc32(kind + data))
    )


def make_png(width):
    height = width // 2
    rows = []
    for y in range(height):
        row = bytearray()
        for x in range(width):
            color = (242, 244, 248)
            if width // 8 <= x < width // 2 and height // 4 <= y < 3 * height // 4:
                color = (70, 100, 160)
            if (x - 3 * width // 4) ** 2 + (y - height // 2) ** 2 < (height // 5) ** 2:
                color = (220, 160, 60)
            row.extend(color)
        rows.append(b"\x00" + row)
    header = struct.pack("!IIBBBBB", width, height, 8, 2, 0, 0, 0)
    return (
        b"\x89PNG\r\n\x1a\n"
        + chunk(b"IHDR", header)
        + chunk(b"IDAT", zlib.compress(b"".join(rows)))
        + chunk(b"IEND", b"")
    )


page = '''<!doctype html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Shape A candidate test</title>
<style>
  body { margin: 0; padding: 16px; font-family: sans-serif; }
  #shape { display: block; width: calc(100vw - 32px); height: auto; }
  @media (min-width: 600.01px) {
    #shape { width: calc(50vw - 32px); }
  }
  @media (min-width: 1200.01px) {
    #shape { width: 568px; }
  }
</style>
<p>Shape A: rectangle and circle</p>
<img id="shape" src="shape-a-800.png" width="1440" height="720"
     alt="Blue rectangle and amber circle on a pale background"
     srcset="shape-a-480.png 480w, shape-a-800.png 800w,
             shape-a-1200.png 1200w, shape-a-1440.png 1440w"
     sizes="(max-width: 600px) calc(100vw - 32px),
            (max-width: 1200px) calc(50vw - 32px), 568px">
</html>
'''

root = Path(tempfile.mkdtemp(prefix="responsive-shapes-"))
for width in (480, 800, 1200, 1440):
    (root / f"shape-a-{width}.png").write_bytes(make_png(width))
(root / "index.html").write_text(page, encoding="utf-8")
handler = partial(SimpleHTTPRequestHandler, directory=str(root))
with ThreadingHTTPServer(("127.0.0.1", 0), handler) as server:
    print(f"Files: {root}", flush=True)
    print(f"Open http://127.0.0.1:{server.server_port}/", flush=True)
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        pass

In Terminal, change to the folder where you saved the program and run:

python3 responsive_demo.py

Open the local address printed by the program in Chrome. Keep Terminal running during the test; press Control+C there when finished. The program requests an available port, so use its printed address rather than assuming a fixed port number.

The CSS thresholds use 600.01px and 1200.01px for the desktop test’s integer viewport widths. Test the exact integer values in the table. When adapting the example to a production layout, align your real CSS breakpoints and source-size conditions, including any fractional-width behavior.

How do you verify the selection in Chrome on a Mac?

Right-click the shape and select Inspect to open DevTools with its image element selected. Chrome documents this as a direct way to inspect an element and its applied styles. Open Chrome DevTools

  1. Click Toggle device toolbar and choose Responsive under Dimensions.
  2. Set the viewport width to 1000.
  3. In the toolbar’s More options menu, choose Add device pixel ratio, then select DPR 2.
  4. If needed, use More options, then Add device type, and select Desktop.
  5. Open Network, enable Disable cache, and reload the page with DevTools open.
  6. Find the requested image by filtering for shape-a.

Chrome documents the viewport, DPR, and device-type controls in its Device Mode guide, and the cache control in its Network features reference.

After the page loads, run this complete diagnostic snippet in the DevTools Console:

(() => {
  const image = document.getElementById("shape");
  if (!image) throw new Error("The Shape A image was not found.");

  const viewport = window.innerWidth;
  const slot = window.matchMedia("(max-width: 600px)").matches
    ? viewport - 32
    : window.matchMedia("(max-width: 1200px)").matches
      ? viewport / 2 - 32
      : 568;

  console.table({
    viewportCSSPixels: viewport,
    devicePixelRatio: window.devicePixelRatio,
    declaredSlotCSSPixels: slot,
    renderedWidthCSSPixels: image.getBoundingClientRect().width,
    targetResourcePixels: slot * window.devicePixelRatio,
    selectedURL: image.currentSrc,
    naturalWidthCSSPixels: image.naturalWidth
  });
})();

This snippet calculates the declared slot specifically for this demo; it is not a general sizes parser. Compare its declared slot with the rendered width, then compare the selected filename with the prediction table.

currentSrc reports the full URL selected by the browser. It does not establish that the resource loaded successfully, so also inspect the image request and the displayed result. Reading src would only reveal the fallback attribute in this example. MDN: HTMLImageElement.currentSrc

Avoid interpreting naturalWidth as the encoded PNG width. It is a density-corrected width in CSS pixels. For this controlled fixture, the generated file’s dimensions and filename identify its resource width. MDN: HTMLImageElement.naturalWidth

Repeat the test at 600 and 601 CSS pixels, reloading for each condition. Record the viewport, reported DPR, slot, selected filename, and whether the request completed. These records distinguish a repeatable fresh-load result from a sequence of choices made while resizing an already loaded page.

What should you check when the prediction differs?

Work through the inputs before changing the candidate list:

  1. Check the descriptor family. With density descriptors such as 1x and 2x, do not apply the width-descriptor calculation through sizes.
  2. Check the first matching condition. An earlier matching condition takes precedence over later entries.
  3. Compare declared and rendered widths. A declaration of 100vw can overstate a slot that CSS limits to a narrow column.
  4. Read the actual DPR. Recheck after page zoom or a display change.
  5. Compare controlled reloads. Keep the same viewport, DPR, and loading conditions while repeating the test.
  6. Check resource availability. A selected URL and a successfully displayed image are separate observations.

Missing or unusable explicit source sizes can lead the HTML parser to its 100vw default. That can explain a surprisingly large target for a narrow image. Supply an accurate source-size list instead of assuming the browser will infer the intended column width from your CSS. HTML Standard: Parsing a sizes attribute

If a page uses a picture element, establish which source branch applies before calculating densities. Its source selection precedes the choice among that branch’s candidates; different crops belong to this art-direction mechanism. Using responsive images in HTML

Which support limits affect this method?

MDN marks the sizes property as widely available across browsers, but that does not make every newer keyword equally supported. The explicit conditions used here provide a straightforward test without relying on automatic sizing. MDN: HTMLImageElement.sizes

sizes="auto" is valid for lazy-loaded images and lets selection use their layout width. If you adopt it, keep explicit fallback sizes after auto for browsers that do not support the keyword, and provide image dimensions. Do not substitute it into this eager-loading example without changing those prerequisites. MDN’s image element reference

Chrome’s device controls exercise Chrome’s behavior under emulated conditions. They do not demonstrate Safari’s or Firefox’s candidate choices. Chrome also describes Device Mode as an approximation, so test another browser directly when that browser’s behavior matters. Chrome DevTools: Device Mode limitations

A useful prediction ends with a checkable record: the applicable source set, resolved source size, reported DPR, calculated target, and observed currentSrc. When those inputs agree with the authored layout, you can explain the resource choice clearly and identify whether the next change belongs in CSS, sizes, or the available image widths.

Sources