srcset alone tells the browser what candidates exist; sizes tells it how large the image will actually render at different viewport widths — together, they let the browser make a genuinely informed, efficient choice.
1The Cost Of Omitting sizes
When srcset uses width descriptors but no sizes attribute is present, browsers apply a default assumption: the image displays at 100% of the viewport width (100vw). For a genuine full-bleed hero image, this default happens to be correct. For anything else — a three-column grid item rendering at roughly 33% of viewport width, a sidebar thumbnail, a card image — this default is significantly wrong, causing the browser to select a candidate sized for full-width display when a much smaller file would have sufficed.
This is a subtle but common source of unnecessary bandwidth waste: the srcset attribute may be perfectly implemented, but without an accurate sizes value, its benefit is significantly undermined for any non-full-width image.
2Writing Accurate sizes Values
The sizes attribute is a comma-separated list of media-condition and width pairs, structurally similar to CSS media queries: sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw" states that below 600px viewport width the image displays at 100% viewport width, between 600px and 1200px at 50%, and above 1200px at 33% (that final, condition-less entry serving as the default fallback).
The browser evaluates this list against the current viewport at load time, combines the resulting display width with the actual pixel widths declared in srcset's w descriptors, and selects the smallest candidate that still satisfies that display requirement at the device's pixel density.
3sizes Must Match Real CSS — Manually
A critical, easy-to-miss detail: the sizes attribute is entirely independent of actual CSS layout rules — the browser doesn't cross-reference it against your stylesheet to verify accuracy. If a CSS refactor changes a grid item's actual rendered width from 33% to 25%, but the sizes attribute isn't updated to match, the browser continues making candidate-selection decisions based on the now-inaccurate, stale sizes value.
This makes sizes a value that requires the same ongoing maintenance discipline as any other piece of markup tightly coupled to a specific layout — worth flagging explicitly in code review whenever a responsive layout's column widths or breakpoints change.
4Step-by-Step Breakdown
Telling The Browser How Big The Image Will Actually Be. srcset's width descriptors tell the browser how big each candidate file *is*. The sizes attribute tells the browser how big the image will actually be *displayed* at different viewport widths — without it, the browser has to guess, and its default guess is often wrong.
Without sizes, The Browser Assumes 100vw. If srcset uses width descriptors but sizes is omitted, browsers default to assuming the image displays at 100% of the viewport width — a reasonable guess for a full-bleed hero image, but wrong (and wasteful) for anything smaller, like a grid item or sidebar image.
The Default Assumption. An image displays at only 30% of the viewport width in a three-column grid layout, but has no sizes attribute. What does the browser assume?
- →It correctly infers 30vw from the CSS grid layout automatically
- →It defaults to assuming 100vw, likely causing it to over-download a larger file than needed
- →The image fails to load without an explicit sizes attribute
sizes Uses Media Conditions To Describe Layout. The sizes attribute is a comma-separated list of media-condition/width pairs, mirroring CSS media queries: '(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw' describes how the image's display width changes across different viewport breakpoints.
Reading sizes Syntax. In 'sizes="(max-width: 600px) 100vw, 50vw"', what does the final, condition-less '50vw' represent?
- →A fallback value applied when no earlier condition matches
- →Invalid syntax; every entry requires a condition
- →It's ignored entirely by browsers
sizes Must Match The Actual CSS Layout. The sizes attribute is entirely independent of and not automatically derived from actual CSS — if the two disagree (sizes claims 50vw but CSS actually renders the image at 33vw), the browser makes selection decisions based on the incorrect sizes value, potentially choosing a suboptimal candidate.
sizes/CSS Mismatch. If an image's sizes attribute claims 50vw but its actual CSS width is 33vw, what happens?
- →The browser automatically detects and corrects the mismatch
- →The browser may select a larger, less optimal candidate than actually necessary, based on the incorrect sizes value
- →There's no real consequence either way
sizes Attribute Mastered. You now understand why sizes is necessary to avoid the wasteful 100vw default assumption, how to write media-condition-based sizes values, and why keeping sizes accurately synced with real CSS layout is essential for correct browser candidate selection.
Tell The Browser The Rendered Width. The sizes attribute lets the browser pick the right srcset candidate before layout.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1sizes Has No Direct Accessibility Impact But Supports Overall Performance, Which Benefits All Users
Faster-loading, appropriately-sized images benefit users on constrained connections or older devices broadly, including many users who also rely on assistive technology.
SEO Implications
- 1
An Accurate sizes Attribute Is Necessary To Realize srcset's Full LCP Benefit
srcset without a correct sizes value can still result in over-downloading for non-full-width images, meaning the two attributes should be evaluated together, not srcset alone, when auditing LCP-related image performance.
Best Practices
Update sizes Values Whenever A Layout Change Affects An Image's Rendered Width
Since sizes isn't automatically derived from CSS, it requires the same deliberate maintenance as any other markup value coupled to a specific layout decision.
Default To Full-Width Images Simplifying To Omitting sizes (Relying On The 100vw Default) Only When Genuinely Accurate
For true full-bleed hero images, the 100vw default is already correct, so an explicit sizes attribute in that specific case adds no value — but this should be a deliberate choice, not an oversight.
Frequent Bugs
A grid of thumbnail images is downloading noticeably larger files than their actual small rendered size would suggest.
Add an accurate sizes attribute reflecting the thumbnail's real rendered width (e.g. 33vw for a three-column grid), rather than relying on the incorrect 100vw default.
After a responsive redesign changes column widths, image loading performance regresses despite srcset remaining unchanged.
Update the sizes attribute to match the new actual rendered widths — it wasn't automatically kept in sync with the CSS layout change.
Real-World Examples
A Three-Column Grid With Accurate sizes
A product grid correctly signaling that images render at roughly a third of viewport width above a tablet breakpoint.
<img
srcset="product-300.jpg 300w, product-600.jpg 600w, product-900.jpg 900w"
sizes="(max-width: 768px) 100vw, 33vw"
src="product-600.jpg"
alt="Blue running shoe, side view"
>