Vyso Blog
Responsive images from one source with Vyso
To serve responsive images from one source with Vyso, define a small set of resize URLs, put them in srcset, and describe the rendered image slot with sizes. Vyso generates the representation requested by each URL. The browser selects a candidate using the supplied markup.
One source does not mean one delivered file. The source stays in the library; the website can request several representations without maintaining separate resized source assets.
one preserved source image
→ explicit candidate URLs: 480, 768, 1200, 1600, 2400 pixels
→ srcset + sizes supplied by the application
→ browser selects and requests a candidate
Keep the source; make delivery variants reproducible
The source asset is the authoritative image retained in the library. A delivery representation is an output generated from that source for a placement, with specified dimensions, crop or format.
A file collection containing hero-original.jpg, hero-mobile.jpg, hero-tablet.jpg, hero-desktop.jpg, hero-retina.jpg and hero-retina-final.jpg mixes source identity with presentation settings. If those files contain only repeatable resizing, the delivery recipe can record those differences.
Vyso's delivery model uses the preserved source and an explicit transformation chain to generate the requested representation. Generated outputs can still exist in caches. They do not each need an independently maintained library asset.
Keep a separate edited asset when it contains meaningful creative work, such as a manually composed campaign crop or retouching. Its responsive sizes can then be generated from that edited source.
Choose widths from the image slot
Measure how wide the image is rendered at the layouts your application supports. A 1440px viewport can contain a card image only 360 CSS pixels wide. Building that card's candidates around the full viewport would give the browser misleading choices.
Use a small set of meaningfully separated widths that covers the placement and relevant display densities. Widths such as 480, 768, 1200, 1600 and 2400 are example choices for the hero below. A small card may need a different set.
A sequence of widths such as 400, 420, 440 and 460 adds recipes to maintain without necessarily improving that placement. Standardize useful candidate sets in application configuration instead of producing a new width for every small layout change.
Generate each candidate through an explicit URL
Vyso's public CDN host is https://cdn.vyso.io. A width-only resize uses a transformation path segment:
https://cdn.vyso.io/resize:width=768/ASSET_ID.jpg
ASSET_ID.jpg means the actual source asset key, including its extension. Use the key returned by the library, not a display filename you have reconstructed.
The resize reference documents the parameters. Specifying width alone preserves aspect ratio. Enlargement is disabled by default, so requesting 1600px from a 900px source does not guarantee a 1600px output.
Verify output dimensions before assigning width descriptors. A candidate labelled 1600w must genuinely be 1600 image pixels wide. Remove an unsupported candidate, provide a larger source, or make a deliberate enlargement decision. Upscaling adds pixels; it cannot recover source detail.
The application defines the recipe once. Vyso generates the requested representation when the delivery URL is used. This workflow does not require an eager export of every possible breakpoint after upload.
Build a complete hero candidate set
Assume a 3600 × 2400 source photograph with a 3:2 aspect ratio. The page-level hero has 16px gutters on each side and a maximum rendered width of 1200 CSS pixels. These styles define that slot:
.hero {
width: calc(100vw - 32px);
max-width: 1200px;
margin-inline: auto;
}
.hero img {
display: block;
width: 100%;
height: auto;
}
The source supports the candidate widths without enlargement. Each URL requests a representation of the same composition:
<div class="hero">
<img
src="https://cdn.vyso.io/resize:width=1200/ASSET_ID.jpg"
srcset="
https://cdn.vyso.io/resize:width=480/ASSET_ID.jpg 480w,
https://cdn.vyso.io/resize:width=768/ASSET_ID.jpg 768w,
https://cdn.vyso.io/resize:width=1200/ASSET_ID.jpg 1200w,
https://cdn.vyso.io/resize:width=1600/ASSET_ID.jpg 1600w,
https://cdn.vyso.io/resize:width=2400/ASSET_ID.jpg 2400w
"
sizes="(max-width: 1232px) calc(100vw - 32px), 1200px"
width="1200"
height="800"
alt="A mountain ridge above a lake at sunrise"
>
</div>
Replace the example key with your source key and supply alternative text for the actual image and placement. The width and height attributes describe its 3:2 ratio, while CSS determines the displayed size. The fallback src uses a 1200px candidate, not the largest available representation.
The w descriptors tell the browser each resource's intrinsic width. The sizes value describes the slot: viewport width minus 32px until the viewport reaches 1232px, then 1200px. The browser uses that information to select a candidate; the markup does not promise that a particular viewport always receives one particular file. The HTML standard defines the candidate and source-size model.
sizes describes the expected slot for selection. It does not create the responsive CSS layout. If the hero moves into a half-width column, update the CSS and sizes together. Leaving sizes="100vw" on that column would describe an image as wide as the viewport.
Account for display density with candidates
A 600 CSS-pixel slot on a display with a device pixel ratio near 2 can benefit from a candidate around 1200 image pixels wide. At the example hero's maximum 1200 CSS-pixel width, the 2400px candidate provides a corresponding higher-density choice.
This does not require sending a 2x image to every visitor. Provide a sensible candidate set and let the browser select from it. Browser selection has discretion; do not build application logic around a guarantee that it will choose a particular width. web.dev's responsive-image guidance explains the relationship between source size, candidate width and display density.
Separate resolution switching from art direction
The hero example performs resolution switching: the composition stays the same while pixel dimensions change. Art direction changes the framing. A wide scene that works across a large page can make the subject too small in a narrow placement.
For the same 3600 × 2400 source, an explicit portrait recipe could extract a 1200 × 1600 center region and then resize it to a width of 480px:
https://cdn.vyso.io/crop:width=1200,height=1600,focus=center/resize:width=480/ASSET_ID.jpg
That recipe produces a different composition. The crop runs before the resize, in URL order. The crop reference documents its dimensions and focus options. A center crop is an explicit choice to inspect on the source, not a prediction of the best framing for every screen.
Use <picture> with media conditions on its <source> elements when the layout needs to switch between crop families. Each family can have its own width candidates. MDN's picture reference explains source selection. Choose the composition first, then generate its candidate dimensions.
Choose format independently of width
Responsive resizing and format selection are separate operations. Vyso's format documentation states that delivery preserves the source format unless an explicit transformation or a format-specific operation changes it.
To request WebP for a 768px candidate, add the format step:
https://cdn.vyso.io/resize:width=768/format:type=webp/ASSET_ID.jpg
Apply the explicit format choice to each URL in a WebP candidate family. Keep the original source key's .jpg extension; the transformation requests the output format, and the response Content-Type identifies it.
If the application needs alternative-format sources, <picture> can declare their types. That remains frontend markup. A resize URL alone does not ask Vyso to negotiate a format from browser capabilities.
Use presets for recipes, not an entire srcset
A delivery preset stores a reusable transformation configuration managed through the authenticated Developer API. For example, after creating an article-768 preset that requests a width of 768px, its representation can use:
https://cdn.vyso.io/preset/article-768/ASSET_ID.jpg
The slug is an example you create in the source asset's workspace. A single preset defines one configuration. It does not supply a complete responsive candidate list.
Use separate configurations for distinct candidate widths, or keep the direct resize URLs shown above. The application still assembles srcset and describes the placement with sizes. Presets do not choose breakpoints or generate HTML.
Reuse stable URLs and check cache behavior
Each candidate URL identifies a requested representation. Reuse the same URL when the source and recipe are unchanged; repeated requests may reuse a generated variant according to the delivery layer's cache behavior.
The caching documentation directs clients to inspect Cache-Control and related response headers. A stable URL does not guarantee that every cache holds the image, that it stays there permanently, or that processing happens exactly once globally.
When changing a source or preset behind an existing URL, account for cache invalidation and check what the consuming page receives. Reproducible variants still need an update strategy.
Check the candidates in the actual page
Vyso handles the requested image transformations and delivery representations. The application owns candidate widths, layout, breakpoints, srcset, sizes, art direction, alternative text, dimensions and loading behavior. This works through ordinary image URLs and HTML, including HTML emitted by a CMS or frontend framework.
Inspect the browser's Network panel or the image's currentSrc property to identify the selected resource. Test representative viewport widths and display densities instead of assuming the largest candidate should always load.
- Check that generated pixel widths match their
wdescriptors. - Compare the rendered slot with the active
sizesvalue, including gutters and constrained columns. - Inspect whether the same composition remains usable in narrow placements.
- Verify the output format and update behavior when sources or presets change.
For compression, loading priority and broader page measurements, use the separate image quality and performance workflow.
Keep going
Make the media library less work.
See how Vyso brings search, enrichment, cleanup, and delivery into one product.
Start free