Website problems

srcset without sizes

A srcset listing width candidates tells the browser which files exist. It does not say how wide the image will be rendered, and the specified default for that is the full viewport width. So an image occupying a third of the layout has a file roughly three times wider than needed selected on nearly every screen — the responsive image markup is present, every audit reports it, and not a single byte is saved.

What the browser does without sizes

It needs a rendered width to choose between width candidates, and it chooses before layout has been computed.

The specification's default is one hundred per cent of the viewport width, which is correct for a full-bleed image and wrong for everything else.

It multiplies that by the device pixel ratio and picks a candidate at least that wide.

On a high-density phone that arithmetic reaches the largest candidate almost immediately.

So the list is consulted and the answer is nearly always the same one.

Why the markup still looks correct

Every tool reporting on responsive images sees a srcset with several candidates and reports it as present.

The page renders identically, because the browser scales whichever file it chose to the rendered size.

The only symptom is transfer weight, which is attributed to the images being large rather than to the wrong one being selected.

Which is why this survives: the markup is there, the page looks right, and the measurement that would reveal it is per-image rather than aggregate.

How to write the sizes attribute

Describe the rendered width at each breakpoint, in the same order the media conditions are evaluated — first match wins.

End with a default value with no condition, which applies when none of the earlier ones match.

Use the same breakpoints as the CSS, because the values have to track the layout rather than approximate it.

Viewport-relative units are usually clearer than pixel values, since the rendered width is usually a proportion.

An approximate value that is close is far better than no value at all, which is the full viewport by default.

When it is not needed

Density candidates rather than width candidates, where the rendered size is fixed and there is nothing to compute.

An image rendered at a fixed size regardless of viewport, which has no reason to carry a srcset at all.

A single candidate, which is a list with no choice in it and is worth simplifying rather than annotating.

Inside a picture element where each source carries its own sizes, the inner image element's attributes apply only to its own srcset.

The maintenance cost nobody plans for

A sizes attribute encodes the layout, so a layout change invalidates it silently.

Nothing fails when it drifts: the browser picks a file based on a width the image no longer has.

Which means it needs to be generated from the same source as the layout where that is possible, rather than written by hand per image.

A component that knows its own rendered width can emit the attribute correctly, which is the durable answer on a design-system codebase.

How to check it yourself

View source and find an image with a srcset using width descriptors — a missing sizes attribute is the defect.

In the network panel, compare the file actually fetched against the space the image occupies on screen.

Do it at a narrow viewport, where the mismatch is largest and most costly.

Check the currentSrc property of the image in the console, which reports the candidate the browser chose.

Compare the chosen file's intrinsic width against the rendered width multiplied by the device pixel ratio.

How VeriFixScan detects it

`images.sizes` reads the sizes attribute and checks it against the layout information available, which is this problem directly.

`images.srcset` validates the srcset syntax, since an invalid list is discarded entirely and produces a different failure.

`images.oversized` identifies files substantially wider than their rendered box, which is the consequence this produces.

`images.responsive` and `mobile.responsive_images` report whether images adapt to the layout at all, at desktop and mobile widths.

Rendered dimensions are derived from the served markup and available layout, so an image sized by script afterwards may be compared against the wrong box.

What the auto value changes

A sizes value of auto lets the browser use the image's actual layout width rather than a declared estimate, which removes the maintenance problem entirely.

It requires the image to carry a lazy loading attribute, because the browser must have completed layout before it can know the width.

Which means it is unavailable for exactly the image this family's other problem is about — the one above the fold that must load eagerly.

So the practical split is auto for below-the-fold images that are lazy anyway, and a written value for the hero.

Support is still uneven, so a written fallback value alongside it is worth keeping for now.

Frequently asked questions

I have srcset on every image. Why is nothing lighter?
Almost certainly a missing sizes attribute. The browser assumes the image spans the viewport and selects the largest candidate on nearly every screen.
Do density descriptors need sizes?
No. They apply to an image rendered at a fixed size, so there is no rendered width to compute. Only width descriptors need it.
What if my sizes value is approximate?
Far better than nothing. An approximate value close to the truth selects a sensible candidate; no value at all selects the largest one almost every time.

Sources

Related

VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.

Scan a website