Responsive images solve a simple problem with surprisingly subtle mechanics: the same visual content is displayed at very different sizes and pixel densities. Sending one huge file wastes data; sending one small file can look blurry.
HTML gives the browser a negotiation mechanism through srcset, sizes, and, when necessary, <picture>. The key is to describe the real layout accurately and let the browser select among well-prepared candidates.
A fluid image is not necessarily a responsive image
max-width: 100% makes an image adapt visually to its container, but the browser may still download the same large file on every device. Responsive images add resource selection: several candidates are offered and the browser chooses one that fits the layout and display density.
Why not send the largest image to everyone?
It is simple but wasteful. A phone displaying an image at a few hundred CSS pixels may download millions of unnecessary pixels. That costs bandwidth, decode memory, and often loading time.
Why not send the smallest image?
Because the same image may be displayed wider on desktop or on a high-density screen. An undersized source can look soft. The objective is not the smallest file in isolation; it is an appropriately sized candidate.
Prepare variants before writing srcset
Generate several widths from a high-quality master. Never create a 1,200-pixel candidate by enlarging a 600-pixel derivative. See Image Resolution and Image Compression.
How many variants?
Enough to avoid huge gaps, but not dozens of nearly identical files. Common widths might include 480, 768, 1024, 1280, and 1600 pixels, adjusted to your real layout and source dimensions.
src still matters
The <img src> remains the fallback and can also be used by browsers as one candidate. Choose a sensible resource rather than automatically pointing it at the largest original.
Width descriptors: w
A width-based set declares each candidate’s intrinsic pixel width:
480w means the file is 480 pixels wide; it is not a media query.
Why sizes exists
With w descriptors, the browser needs an estimate of the image’s rendered CSS width before layout is complete. sizes describes that slot. The browser combines slot width with device pixel density and other factors to choose a candidate.
Understanding vw
100vw means the slot is approximately the full viewport width. It does not mean the file itself is 100 pixels or that the image is necessarily full width after CSS constraints.
A simple sizes="100vw" example
For a genuinely edge-to-edge mobile hero, 100vw can be reasonable. For an article image inside a 720-pixel container on desktop, keeping 100vw at every breakpoint can make the browser choose unnecessarily large files.
The browser chooses, not the developer
srcset is a set of candidates, not a strict command to fetch a particular URL at a breakpoint. Browsers can consider device pixel ratio, cache state, and implementation heuristics.
Container-limited image
If an article body is min(100% - 2rem, 720px), the image slot is close to the viewport on small screens and about 720px on larger ones. Your sizes should communicate that behavior rather than merely copy CSS breakpoint names.
The order of sizes conditions matters
The browser evaluates media conditions from left to right and uses the first matching slot size, with the final value acting as the default. Put specific conditions before the fallback.
Does sizes have to reproduce CSS exactly?
It should approximate the actual rendered width closely enough for good candidate selection. It does not need to reproduce every layout declaration, but systematic overestimation wastes bytes.
Grid example
A three-column grid might give each card roughly one third of the container width on desktop, half on tablet, and full width on mobile. Describe those slots in sizes; do not use 100vw for every card.
A bad sizes can cancel the optimization
If a 320px card declares sizes="100vw" on a 1440px monitor, the browser may select a much larger candidate than necessary. The files can be perfectly compressed and the page can still be heavy.
Density descriptors: x
For images whose CSS size is fixed or predictable, density descriptors can be simpler:
2x targets roughly twice the source pixels per CSS pixel.
When should you use x?
Use density descriptors for fixed-size icons, avatars, or assets where layout width does not vary much. For fluid content images, w plus sizes is usually more expressive.
Do not mix w and x in the same srcset
Choose one descriptor model for a candidate set. Width descriptors already allow the browser to account for device pixel ratio through the slot calculation.
How does selection work with w?
Conceptually, the browser estimates the slot width from sizes, multiplies by an appropriate density requirement, and chooses from the declared intrinsic widths. Exact algorithms and heuristics are browser-controlled.
Why might a 400px slot download an 800px file?
A device pixel ratio of 2 can make 800 source pixels appropriate for a 400 CSS-pixel slot. This is expected and is why comparing only CSS width with file width can be misleading.
Do you always need exact DPR?
No. Network cost and visual benefit must be balanced. Browsers may choose nearby candidates, and a slightly lower source density can still look excellent for photographic content.
Resolution, compression, and format still matter
Responsive markup cannot rescue poor derivatives. Generate candidates from a good master, resize correctly, compress them appropriately, and choose suitable formats. See Image Format Comparison.
What is <picture> for?
<picture> provides multiple <source> elements before a final <img>. It is useful for format alternatives and art direction. You do not need <picture> merely to use srcset.
Using <picture> for formats
You can offer AVIF, then WebP, then a fallback image. Each source can have its own srcset. The browser selects a supported source type and then chooses an appropriate candidate within it.
Using <picture> for art direction
Art direction means serving a genuinely different crop or composition for a different layout. A mobile portrait crop can focus on the subject while desktop uses a wide landscape version.
Resolution switching vs art direction
Resolution switching keeps the same visual content and varies pixel dimensions. Art direction changes the framing or even the source artwork. Keep these goals conceptually separate.
Do not use <picture> to micromanage every device
Responsive images are designed to let browsers select resources. Hard-coding a different source for every imagined device creates brittle markup and maintenance overhead.
The final <img> is essential
It provides the fallback, alternative text, intrinsic dimensions, loading attributes, and the actual image element. <source> does not replace the semantic role of <img>.
Alternative text
All responsive variants representing the same information share the alt on the final <img>. Do not put alt on <source>. If art direction changes the information itself, reconsider the design so accessibility remains equivalent.
Keep width and height
Intrinsic dimensions help the browser reserve space and reduce layout shift. When all candidates share an aspect ratio, use dimensions corresponding to that ratio; CSS can still scale the image responsively.
Generate variants without degrading them
Always derive widths from the master or another sufficiently high-quality source. Avoid repeated lossy re-encoding chains. Apply sharpening or quality tuning only when the resizing workflow genuinely needs it.
Naming variants
Use predictable names such as hero-480.webp, hero-800.webp, and hero-1200.webp, or let a build pipeline generate hashed URLs with metadata. The descriptor in markup must match the actual intrinsic width.
Which candidate belongs in src?
Choose a sensible middle or fallback candidate that works when srcset is ignored. Do not make src the full-resolution original by reflex.
Hero images and LCP
A hero is often the Largest Contentful Paint element. Do not lazy-load it. Make it discoverable early, use accurate responsive markup, and consider fetchpriority="high" only for genuinely important candidates.
Lazy loading
loading="lazy" is valuable for below-the-fold images. Applying it to everything can delay important content. Responsive selection and lazy loading solve different problems.
decoding and fetchpriority
decoding="async" can be useful for many noncritical images. fetchpriority is a hint about network priority, not a replacement for correct markup. Avoid marking many images high priority.
Why DevTools can surprise you
Browsers cache resources and may not download a smaller candidate after a larger one is already available. Resize tests can therefore look wrong. Use a clean reload, appropriate cache settings, and inspect currentSrc.
Use currentSrc
In the console or DOM properties, img.currentSrc reveals the resource the browser selected. Combine it with the rendered width and network transfer size to understand whether sizes is accurate.
Test several viewport widths and densities
A responsive setup should be tested on narrow mobile, larger mobile, tablet, and desktop widths, with representative device pixel ratios. Verify both visual sharpness and transferred bytes.
The combinatorial explosion problem
Five widths × three formats × several crops can create dozens of files per source. Generate only combinations that deliver measurable value. Automation helps, but storage and build time still matter.
Image CDNs and automated pipelines
An image CDN can create width and format variants on demand. A static build can generate them ahead of time. Both approaches should keep a trustworthy master and deterministic transformation rules.
Can the browser choose based on bandwidth?
Browser selection can include implementation heuristics and environmental information, but authors should not rely on a precise bandwidth-based promise. Give the browser sensible candidates and accurate slot information.
Does srcset guarantee the smallest file?
No. Selection is based primarily on suitability, not on comparing the byte size of every candidate. Two 800w files can have very different weights depending on content and encoding.
Why can a larger candidate remain after resizing the window?
Browsers generally avoid replacing an already downloaded high-resolution image with a smaller one simply to save memory or bytes that have already been transferred. Test from fresh page loads when evaluating selection.
Responsive images and SEO
Responsive delivery can improve performance without hiding the semantic image. Keep meaningful alt, stable URLs where appropriate, crawlable resources, and correct HTML. Performance gains support page quality but are not an SEO trick.
Responsive images and accessibility
Every candidate should convey equivalent information unless art direction intentionally changes framing. Ensure important content is not cropped out for mobile users and keep alternative text appropriate.
SVG and responsive behavior
Pure vector SVG often needs only one source because it scales without fixed raster resolution. CSS sizing and a correct viewBox are usually more important than srcset. See SVG Format.
Metadata and privacy
Generating variants can copy EXIF, GPS, or other metadata into every derivative. Decide your public metadata policy once and apply it consistently. See Image Metadata and Privacy.
Case study: full-width hero
Generate several large widths, use w descriptors, write sizes to match the actual hero slot, avoid lazy loading, declare dimensions, and test LCP on a throttled connection.
Case study: article image
If the article column maxes out around 720px, provide widths around the mobile and column needs rather than desktop viewport width. A 1440px candidate may still be useful for high-density displays but should not be the default download.
Case study: grid cards
Describe card slot widths at each layout breakpoint. The most common error is declaring viewport width even though three cards share the row.
Case study: fixed avatar
A 64px avatar is a good candidate for 1x and 2x density descriptors. Width descriptors add little when the CSS slot is fixed.
Case study: mobile crop
Use <picture> with media conditions for the crop, not merely for a smaller copy. Keep the subject and essential information present in every composition.
Case study: AVIF + WebP + widths
Each format source can declare the same width ladder. The browser first finds a supported source and then selects the candidate. Keep the final <img> fallback.
How should you choose width breakpoints?
Base them on actual rendered slots and useful density ranges, not arbitrary round numbers alone. Avoid variants so close together that they rarely change the browser’s decision.
Do not upscale beyond the original
Creating a 2400w derivative from a 1200px source does not add detail. Stop at the source’s useful intrinsic resolution unless a separate high-resolution master exists.
Why can an image still look blurry?
The selected candidate may be too small for the slot and DPR, the source itself may be soft, CSS may upscale it, or compression may have removed detail. Inspect currentSrc and intrinsic dimensions.
Why can a page remain heavy?
Common causes are inaccurate sizes, too many above-the-fold images, oversized source ladders, excessive quality, poor formats, and decorative assets that should not exist. Responsive markup is one part of a larger optimization system.
Common errors
Do not confuse viewport and container width; do not use x for highly fluid images; do not declare incorrect w values; do not use sizes with an x set; do not omit <img> from <picture>; do not put alt on <source>; and do not lazy-load the LCP image.
Pre-publication checklist
Verify every candidate’s real width, aspect ratio, compression, and format. Check sizes against CSS, preserve alt, declare dimensions, test currentSrc at several viewports/DPRs, inspect network bytes, and repeat with a cold cache.
Recommended Bethemesh workflow
Start with a master, resize with the image resizer, convert formats with the image converter, compress deliberately, then write srcset and sizes from the dimensions you actually generated.
Writing sizes from the layout, step by step
A reliable way to write sizes is to ignore image filenames at first and look only at CSS. Ask how wide the image slot is at each relevant viewport. If a mobile article uses almost the full viewport minus 32 pixels of padding, the slot is roughly calc(100vw - 32px). If the desktop article column stops growing at 720px, the final sizes value can be 720px.
For a card grid, calculate the card width rather than the page width. If two cards share a 900px container with a 24px gap, each image is around 438px, not 900px. A three-column desktop grid makes the difference even larger. This is why copying breakpoint values without thinking about container geometry often produces oversized downloads.
You do not need perfect mathematical reproduction. sizes is a resource-selection hint that is evaluated before final layout. A close, stable estimate is usually better than an extremely complicated expression that nobody maintains when the design changes.
Whenever the layout is redesigned, include responsive image declarations in the review. A sizes string that was accurate for a two-column grid can become wrong after the component moves to three columns even though the image markup itself did not change.
Choosing candidates with byte cost in mind
Width ladders should reflect both layout and compression behavior. If a 640w candidate is 55 KB and the 720w candidate is 58 KB, keeping both may provide little benefit. If the next candidate jumps from 640w at 55 KB to 1200w at 160 KB, an intermediate width may be valuable.
This does not mean the browser selects candidates by comparing their byte sizes. It generally does not. It means you, when designing the candidate set, should avoid expensive gaps and redundant variants.
Measure representative photographs, screenshots, and illustrations because file-size growth is not perfectly proportional to pixel count. A width ladder that works well for photographs may be unnecessarily dense for simple graphics.
Also remember that format and width interact. AVIF, WebP, and JPEG variants of the same intrinsic width can have different byte costs. If maintaining several formats, make sure each format family has sensible quality settings rather than applying one generic export preset.
Art direction without losing meaning
A mobile crop should preserve the information that made the image useful. If a desktop photograph shows a person demonstrating a product and the mobile crop keeps only the person’s face, the visual meaning may have changed. Art direction is not merely a performance trick; it is an editorial decision.
The alt text belongs to the <img> and therefore describes the responsive image concept as a whole. If different sources would require contradictory alternative text, that is a sign the variants may not be semantically equivalent enough to belong to one responsive image.
For purely decorative imagery, different crops can be much freer. For diagrams, screenshots, and evidence-bearing photographs, prefer preserving the complete information or redesigning the mobile presentation rather than cropping away essential content.
Debugging a responsive image that looks wrong
Start by checking currentSrc, the image’s rendered CSS width, its intrinsic natural width, and the device pixel ratio. If the natural width is much smaller than rendered width × DPR, softness is expected. If it is much larger, the problem may instead be source quality, CSS scaling, or compression.
Next inspect sizes. A browser that selected a surprising candidate may be following exactly the slot size you declared. Verify the active media condition and remember that the order of conditions matters.
Then test with a cold cache. Browsers can reuse a previously downloaded larger candidate, making it appear that changing the viewport had no effect. Finally, confirm that every w descriptor matches the actual file width; incorrect descriptors make the browser’s calculations fundamentally unreliable.
Maintaining responsive images over time
Treat responsive image configuration as part of the component API. Centralize common width ladders and sizes patterns where your framework allows it. Document which components are full-width, container-limited, grid-based, or fixed-size.
Automated tests can verify that generated candidates exist, that declared widths match metadata, and that no source is accidentally larger than the master. Performance monitoring can identify pages where new content bypasses the pipeline.
The objective is not to create the most elaborate srcset possible. It is to give browsers a small, trustworthy set of alternatives that remains aligned with the real layout as the site evolves.
What to remember
srcset supplies candidates; sizes describes the slot for width descriptors; the browser makes the final selection. Use w for fluid images, x for predictable fixed-size assets, and <picture> for format alternatives or art direction.
Frequently asked questions
Is srcset enough without sizes? With w descriptors, an omitted sizes effectively leads to a viewport-based assumption that may be wrong for contained images.
Can I mix w and x? Not in one candidate set.
Do I need <picture> for WebP? It can be useful for format alternatives, though modern support policies may simplify the markup.
Should the hero be lazy-loaded? Usually no if it is the LCP image.
How do I know which file loaded? Inspect currentSrc and the Network panel.