ScreenshotNeo

BlogHow-to

How to Automatically Generate Images for Responsive Web Design

Generate image variants in a build or on demand, then use srcset, sizes, and picture so browsers load the right size and crop.

By the ScreenshotNeo team4 October 202612 min read

To automatically generate images for responsive web design, create multiple image variants from each source image—during your build or on demand—and expose them with HTML’s srcset and sizes attributes. The browser chooses a suitable resolution for the image’s rendered slot. Use <picture> when the composition or crop should change at a breakpoint. You do not need a hosted image service or JavaScript to use responsive image markup.

CSS such as max-width: 100%; height: auto keeps an image within its container, but it does not make the browser download a smaller source file. To reduce transferred image data, provide candidate files and describe the layout slot. [MDN: Using responsive images in HTML; web.dev: Responsive images]

1. Decide what should change: size or composition

Need Use What changes
Same image, different display widths or screen densities srcset and, for width candidates, sizes The browser selects among differently sized files of the same composition.
Different crop or composition on mobile, tablet, or desktop <picture> with media-qualified <source> elements The selected image itself changes to fit the design.
Only need an image to shrink within its container Responsive CSS The rendered size changes; the downloaded source may still be unnecessarily large.

These solve separate problems. Use srcset to offer resolution choices for the same content. Use picture for art direction. They can be combined when each art-directed crop also needs multiple resolutions. [MDN]

2. Generate a practical set of candidate files

Start from a high-quality source image and create a controlled range of widths that match the actual slots on your site. For example, a card displayed at roughly half of a wide content area and full width on narrow screens could be served from candidate files around 400, 800, and 1200 pixels wide. These are example dimensions, not a universal breakpoint set. Choose sizes from your real layout and image library.

Each w descriptor in srcset must equal the referenced file’s intrinsic pixel width. Do not label a 700-pixel file as 800w. Keep the image’s composition and aspect ratio consistent across a resolution-switching set unless art direction is intended.

Choose where generation happens

  1. Build pipeline: Generate a known set of sizes and, if needed, formats from source assets during the site build. Store or publish the variants with the site and emit their URLs in markup. This keeps generation tied to deploys and avoids requiring an image transformation service at request time.
  2. Dynamic image service: Store an original and construct transformation URLs for requested widths or formats. Put those transformed URLs in srcset. This can reduce manual asset handling for uploads or large libraries, while adding a service dependency, transformation configuration, and cache behavior to manage. Cloudinary documents URL-based transformations and programmatic breakpoint generation as one implementation option. [Cloudinary: Responsive images using HTML and dynamic image transformations]
  3. CSS only: Use when preventing overflow is enough. It changes display geometry, not which file is downloaded.

Do not generate a huge set of nearly identical widths without a reason. Too many variants complicate storage and delivery and can fragment caches; too few can cause browsers to download files much wider than their display slot. Let your layout slots and actual source dimensions guide the candidate set. [Cloudinary responsive image guidance]

3. Use srcset and sizes for resolution switching

For width-descriptor candidates, sizes describes the expected rendered slot width. It is a hint about layout, not a list of image widths and not a replacement for CSS. The browser uses it along with the candidate widths and device conditions to select a resource.

<img
  src="/images/photo-800.jpg"
  srcset="/images/photo-400.jpg 400w,
          /images/photo-800.jpg 800w,
          /images/photo-1200.jpg 1200w"
  sizes="(min-width: 60rem) 50vw, 100vw"
  width="1200"
  height="800"
  alt="A cyclist riding along a forest trail"
>

This example assumes the image occupies about half the viewport at widths of 60rem and above, and the full available width below that. Adjust sizes to match the real CSS, including page gutters, max-width containers, grid columns, and gaps. The width and height values describe the source image’s intrinsic dimensions and let the browser reserve its aspect ratio before download.

What the browser does

  • srcset lists the permitted resources and their intrinsic widths.
  • sizes states the expected slot width using media conditions and a length such as 50vw or 600px. A percentage is not a valid slot length here.
  • The browser evaluates the conditions in order and uses the first matching slot-size rule; the final value without a condition is the fallback.
  • The browser chooses a candidate using the slot size and its knowledge of display density and other conditions. You provide candidates; you do not need JavaScript to swap them for ordinary responsive delivery.
  • src remains a fallback for browsers that do not use the candidate list.

For a fixed CSS display size where only screen density needs to vary, density descriptors can be simpler. For example, offer a 1x and 2x resource with srcset="/images/avatar.jpg 1x, /images/avatar-2x.jpg 2x"; sizes is not needed for this density-descriptor pattern. Do not mix width (w) and density (x) descriptors in the same srcset. [MDN: resolution switching]

4. Use picture when the crop should change

When a wide desktop image becomes an unhelpfully tiny subject on mobile, create a tighter mobile crop and select it with picture. Include a fallback img with meaningful alternative text. Order media conditions from the most specific match to the fallback source.

<picture>
  <source
    media="(max-width: 40rem)"
    srcset="/images/trail-rider-portrait.jpg"
  >
  <img
    src="/images/trail-rider-landscape.jpg"
    width="1600"
    height="900"
    alt="A cyclist crossing a forest trail"
  >
</picture>

The mobile file should be deliberately cropped to keep the important subject visible. picture does not itself resize or generate your images; it lets the browser select among sources. For multiple resolutions of each crop, each source can have its own srcset and sizes. Use media conditions in picture when the image composition changes; avoid duplicating the same art-direction conditions in sizes. [MDN: Art direction]

5. Complete page example: responsive image card

This standalone HTML example uses illustrative local filenames. Create files at those paths, or replace the URLs with variants generated in your own pipeline or image service. The width descriptors must match the actual intrinsic file widths.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Responsive image card</title>
  <style>
    * { box-sizing: border-box; }
    body { margin: 0; padding: 1rem; font: 1rem/1.5 system-ui, sans-serif; }
    .grid { display: grid; grid-template-columns: 1fr; gap: 1rem; max-width: 72rem; margin: auto; }
    .card { overflow: hidden; border: 1px solid #ddd; border-radius: .75rem; }
    .card img { display: block; width: 100%; height: auto; }
    .card h2, .card p { margin: .75rem 1rem; }
    @media (min-width: 48rem) {
      .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    }
  </style>
</head>
<body>
  <main class="grid">
    <article class="card">
      <picture>
        <source
          media="(max-width: 40rem)"
          srcset="/images/forest-portrait-400.jpg 400w,
                  /images/forest-portrait-800.jpg 800w"
          sizes="100vw"
        >
        <img
          src="/images/forest-landscape-800.jpg"
          srcset="/images/forest-landscape-400.jpg 400w,
                  /images/forest-landscape-800.jpg 800w,
                  /images/forest-landscape-1200.jpg 1200w"
          sizes="(min-width: 48rem) 50vw, 100vw"
          width="1200"
          height="800"
          alt="Sunlight falling across a forest trail"
          loading="lazy"
          decoding="async"
        >
      </picture>
      <h2>A trail through the forest</h2>
      <p>A short description of the place shown in the image.</p>
    </article>
  </main>
</body>
</html>

The layout is one column below 48rem and two columns above it. The mobile crop is selected through the picture media condition; within each composition, srcset offers width variants. The sizes values must continue to match the actual layout if you change the grid or container.

6. Automate variants with an image service

A dynamic transformation service can build variants from a stored original when a requested URL is first delivered. A service’s URL syntax and transformation options vary, so keep its URL construction in your asset layer and generate the HTML candidates from the same source of truth. Cloudinary’s documented approach uses dynamic transformation URLs with HTML responsive image markup, and offers breakpoint generation to help choose candidate widths. This is optional: browser-native srcset and picture work with ordinary static files too. [Cloudinary responsive HTML documentation; Cloudinary: Responsive images]

Whichever system generates the files, optimize for the use: appropriate pixel dimensions, image format, and visual quality. Cloudinary documents automatic format and quality options such as f_auto and q_auto for its own delivery URLs, with cases where exact format or quality control is needed. Treat those as provider-specific URL features, not HTML attributes or universal defaults. [Cloudinary: Optimize Images]

Automation checklist

  1. Preserve an original source image at sufficient quality for the largest intended use.
  2. Define image roles and layout slots: hero, card, thumbnail, product image, and any art-directed crop.
  3. Generate a modest set of widths that covers those slots and likely display densities.
  4. Generate alternate crops only where the design needs a different composition.
  5. Record each candidate’s actual width and height, format, and stable URL.
  6. Emit srcset, accurate sizes, fallback src, dimensions, and alt text from the same asset metadata.
  7. Review delivery and cache behavior when using a dynamic service, including what happens when a new variant is requested.
  8. Inspect actual network requests at representative viewport sizes and device pixel ratios.

7. Loading, layout stability, and accessibility

Reserve the image’s space

Set numeric width and height attributes when the image dimensions are known. The browser can use their aspect ratio to reserve space before the image loads, reducing layout movement. CSS can still set width: 100%; height: auto for flexible rendering. For art-directed crops with different aspect ratios, ensure the displayed crop’s space is also accounted for in the layout.

Lazy-load only images that start below the fold

Use loading="lazy" for below-the-fold content that does not need to appear immediately. Do not blindly lazy-load a prominent hero or another important image at the top of the page; delaying it can delay when that visual appears. fetchpriority="high" can prioritize a genuinely important image, but use it sparingly rather than promoting every image.

<img
  src="/images/article-800.jpg"
  srcset="/images/article-400.jpg 400w, /images/article-800.jpg 800w"
  sizes="(min-width: 60rem) 50vw, 100vw"
  width="1200"
  height="800"
  alt="A close view of a red maple leaf"
  loading="lazy"
  decoding="async"
>

For an important above-the-fold image, omit loading="lazy". Consider fetchpriority="high" only when that image is truly a loading priority. Keep useful alt text for content images; decorative images should not be given misleading descriptions. [web.dev responsive image guidance]

8. Verify which variant the browser downloads

  1. Open the page at representative narrow, medium, and wide viewport widths.
  2. Check the rendered image slot against your CSS and the corresponding sizes condition.
  3. In browser developer tools’ Network panel, filter to images and inspect the requested URL. Disable the cache during repeated checks if a previous request makes the result confusing.
  4. Repeat at different device pixel ratios where possible. A higher-density display may select a larger candidate for the same CSS slot.
  5. Check the selected asset’s dimensions and visual quality, not just the filename.
  6. Test a narrow viewport on a real mobile browser or its remote debugging tools if desktop window resizing does not reach the intended viewport.
  7. Check that each candidate URL loads, that fallback src works, and that art-directed crops retain their subject.

MDN recommends using browser network tools to see which image resources were loaded. Candidate choice belongs to the browser, so a different candidate can be reasonable under different display or network conditions. [MDN responsive image guide]

9. Performance, reliability, and cost trade-offs

Approach Performance considerations Reliability and operating cost
Build-time variants HTML can reference ready-to-serve files directly; choosing appropriate candidates still depends on correct markup. Requires build work and storage for variants. Delivery does not need a transformation request at image view time.
Dynamic transformation service Can avoid pre-generating every possible size; delivery depends on URL configuration and cache behavior. Adds a provider and transformation setup to operations. Review current provider terms and pricing for your usage; no vendor price comparison is established here.
CSS-only resizing Prevents overflow and scales the display, but may transfer a large source file to a small screen. Simple to operate, but does not automate resource selection.

Do not assume one breakpoint list or file format is optimal for every site. Too many variants can reduce cache reuse and increase asset complexity; too few can result in oversized downloads. Optimize dimensions and quality for the image’s intended role, and verify real resource selection. [Cloudinary responsive HTML documentation; Cloudinary image optimization guidance]

10. Troubleshooting

Symptom Likely cause Fix
Mobile still downloads a large file sizes describes a larger slot than the CSS creates, or the srcset candidates are too coarse. Measure the real slot at that viewport, correct the first matching sizes condition, and add a candidate near common slot widths.
The wrong crop appears The picture media condition does not match the layout, or source order makes another condition match first. Align media conditions with CSS breakpoints and put the intended narrower or more specific source first. Keep the fallback img last.
Browser downloads two candidate images JavaScript changes src after the browser has already started loading the original, or markup causes a second independent image request. Use browser-native srcset/sizes for ordinary resolution selection instead of swapping sources after load begins. Inspect the Network panel to identify both request initiators.
Image is blurry on a high-density display The largest candidate is smaller than the rendered CSS width multiplied by the display density, or a width descriptor is inaccurate. Provide a sufficiently large candidate and ensure each w descriptor equals its file’s actual width.
Image is stretched or distorted CSS forces both rendered dimensions to values that do not preserve the aspect ratio, or variant dimensions differ unexpectedly. Use width: 100%; height: auto for proportional scaling, or deliberately define a crop container with object-fit. Keep metadata and crop behavior consistent.
Page content jumps when the image loads The browser did not know the image’s aspect ratio before download. Add accurate width and height attributes and account for crop-specific aspect ratios.
Hero image appears late The visible, important image was lazy-loaded or deprioritized. Remove loading="lazy" for the prominent above-the-fold image. Reserve high fetch priority for the genuinely important image.
Image request fails A candidate URL is wrong, unavailable, or generated using incorrect transformation parameters. Open each candidate URL directly, check server response and transformation configuration, and preserve a valid fallback src.
Narrow desktop resize does not select the small candidate The desktop browser window may not reach the viewport width you expect, or an earlier resource remains cached. Inspect the actual viewport width, use a mobile emulation or device, and disable cache while debugging repeated requests.

11. Or skip the browser setup

If your goal is to capture a website as an image rather than build the image-delivery markup for your own site, ScreenshotNeo is a website screenshot API and MCP server. Its API takes a URL and returns an image or PDF; it captures pages, rather than generating responsive source-image variants for your site. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners, popups, and chat widgets are removed before the shot.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed; response headers say which outcome occurred.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients.
  • 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000. Every feature is on every plan.

Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots per month with no card.

12. Frequently asked questions

Does responsive image markup require JavaScript?

No. For ordinary resolution selection, the browser evaluates srcset and sizes from the HTML before a JavaScript source swap would be useful.

Do I need Cloudinary or another hosted image service?

No. A build can generate static variants, and native HTML can select among them. A hosted service is optional when on-demand transformations or upload workflows suit your operations.

Can one image tag offer both alternate crops and multiple sizes?

Yes. Put art-directed source elements in picture, and give each relevant source its own width-based srcset and sizes. Keep the img fallback.

Is ScreenshotNeo an image transformation service?

No. ScreenshotNeo captures rendered web pages as screenshots or PDFs; it does not generate responsive variants of source images for a site.