Vyso Blog
How to balance image quality and web performance
To reduce image weight without unnecessary quality loss, first deliver an image that fits its placement. Match the dimensions to the page, offer useful responsive candidates and choose an output format. Tune compression after those decisions. A heavily compressed oversized image still sends pixels the page does not need.
The working order is dimensions, responsive candidates, format, compression quality, loading priority, measurement and visual review. Keep the original separately so each delivery representation can be generated from the same source.
Start with dimensions, not compression
Consider a 4000 × 2667 photograph displayed in a content slot roughly 1200 × 800 CSS pixels. Before changing JPEG quality from 90 to 75, check whether the page is downloading the full source. At standard display density, a candidate around 1200 pixels wide is a more appropriate starting point. Higher-density displays may justify larger candidates.
Four different measurements affect that decision. Source dimensions describe the original file. Candidate dimensions describe a generated image the browser can download. The rendered slot is the image's size in the CSS layout. Device pixel ratio describes the relationship between CSS pixels and device pixels.
A 600 CSS-pixel slot on a display with a device pixel ratio of 2 can benefit from a 1200-pixel candidate. That does not mean every image needs an unconditional double-size export. Offer candidates that cover the placements you actually use and inspect the results on representative screens. Google's guidance on serving images at appropriate dimensions explains why CSS scaling alone does not reduce the downloaded file.
Measure the slot at more than one viewport width. An image that fills the page on mobile may occupy only one column on desktop. Also check the crop: shrinking a wide photograph does not necessarily make its subject readable in a narrow card.
Give the browser useful responsive candidates
Use srcset to list candidate files and their actual pixel widths. Use sizes to describe the rendered slot. The browser uses those hints and display density when choosing a candidate. MDN's responsive-image guide covers the markup in more detail.
This example assumes a 3:2 photograph that fills the viewport up to a maximum width of 1200 CSS pixels, with no horizontal gutters:
<img
src="hero-960.webp"
srcset="
hero-640.webp 640w,
hero-960.webp 960w,
hero-1280.webp 1280w,
hero-1600.webp 1600w
"
sizes="(max-width: 1200px) 100vw, 1200px"
width="1200"
height="800"
style="display:block;width:100%;max-width:1200px;height:auto"
alt="A red hiking jacket worn on a snowy mountain trail"
>
The four filenames stand for separately generated candidates. Adapt sizes to the actual layout, including gutters and columns; it does not set the image's CSS width. Check high-density displays too. This example caps available detail at a 1600-pixel candidate, which may need adjustment for a large placement.
A small set of meaningfully separated widths is easier to maintain than exports at 400, 420, 440, 460 and every subsequent increment. Add a candidate when testing reveals a useful gap. Each additional variant adds another output to generate and cache, as web.dev's image-performance guidance explains.
Choose the format before fine-tuning quality
Compare formats at the intended dimensions. JPEG, WebP and AVIF are candidates for photographic content; their relative file sizes and visible artifacts depend on the image and encoding settings. For screenshots, line art and graphics with small text, inspect edge clarity carefully. PNG's lossless compression can be useful when preserving those pixels matters. Transparency is another requirement to check.
The decision is whether an output meets the visual and compatibility requirements at an acceptable size. MDN's image-format guide covers format capabilities and fallbacks. When different browser capabilities require alternatives, the frontend can provide explicit sources through <picture>.
Vyso's output-format documentation describes an explicit choice: delivery preserves the source format unless a format transformation or a format-specific operation changes it. Build the URLs for the formats your application needs.
Tune compression in the actual placement
Use the lowest quality setting that still looks acceptable where the image will appear. JPEG quality 80 is not a universal target, and a quality value in one format is not equivalent to the same value in another. Even encoders for the same format can interpret their quality settings differently. Google's compression guidance explains why there is no universal setting.
Hold dimensions and format constant while comparing a few quality settings. Record the file size for each result. Otherwise, a format change or a smaller export can be mistaken for a benefit from lowering quality.
For photographs, look for uneven skin tones, banding in skies or gradients, smeared foliage and lost texture in the subject. For sharp graphics, inspect small text, lines and flat-color boundaries. A product detail that helps a buyer understand the item deserves more attention than an indistinct background.
Review the candidate inside the page at its intended size, including a realistic mobile viewport and a relevant high-density display. A defect visible only at an enlarged inspection scale may not justify a heavier file. If lettering becomes hard to read or a product's texture changes visibly in the placement, raise quality or reconsider the format or candidate dimensions.
Generate each comparison from the preserved source. Repeatedly editing and saving a lossy delivery copy can add degradation before the final export.
Set loading priority for the image's role
An important hero image needs early discovery as well as a suitable file size. Keep its URL discoverable in the initial HTML where possible. If it is the page's Largest Contentful Paint (LCP) image, avoid loading="lazy". Consider fetchpriority="high" for that image, then verify the request timing. Applying high priority across the gallery defeats the purpose.
A preload can help when an important image would otherwise be discovered late, such as a CSS background. Confirm that it requests the representation the page will actually use; a mismatched preload can create an unnecessary download. web.dev's LCP guidance explains these discovery and priority decisions.
For suitable images farther down the page, native loading="lazy" can defer requests until they approach the viewport. The frontend sets that behavior. Reducing bytes alone does not guarantee a better LCP result: resource discovery, request priority, server response and rendering delays also affect when the image becomes visible.
Preserve the source and generate delivery representations
The original is the reusable asset. A delivery representation is an output for a particular placement. Keep both roles clear, whether variants come from a build process, an image service or an application pipeline.
Overwriting the original with a compressed 640-pixel export saves the wrong file. A future larger placement, different crop or new format may need information that export discarded. Preserve the authoritative source and make delivery outputs reproducible from it.
Use Vyso for explicit image transformations
Vyso's image-delivery system uses the source asset key and a transformation chain in the public CDN URL. A width-only resize preserves aspect ratio. For a JPEG source, this example requests a 1200-pixel-wide WebP representation and applies an explicit quality value:
https://cdn.vyso.io/resize:width=1200/format:type=webp/quality:value=80/ASSET_ID.jpg
ASSET_ID.jpg represents the actual source asset key, including its original extension. Keep that key unchanged when requesting WebP. The response's Content-Type identifies the delivered format. The chain runs in order, so the quality step follows the selected format. Here, 80 is a comparison setting to test, not a recommendation for every image.
The quality step accepts whole numbers from 1 to 100. Its meaning depends on the encoder: for JPEG, WebP and AVIF it controls lossy encoding quality; for PNG it controls lossless compression effort. Lowering that PNG value is not the same visual tradeoff as lowering JPEG quality.
Change the requested width to generate individual candidates for responsive markup. The resize reference documents the parameters. Resizing does not enlarge a smaller source by default, so verify that each output really has the width declared in srcset.
For a transformation used repeatedly, delivery presets let you save a configuration and request it through a URL such as https://cdn.vyso.io/preset/social-card/ASSET_ID.jpg. Use a preset when its configuration fits a repeated placement.
Your frontend still determines the rendered slot, candidate list, sizes, alt text and loading priority. The delivery URL specifies the image representation; the application supplies its publishing context.
Reuse stable variants and check caching
A stable transformation URL identifies a reusable representation. Reuse that URL for the same output instead of adding a changing timestamp on every page render. Vyso's caching documentation describes reuse of generated variants and directs clients to inspect response headers.
Check Cache-Control and related headers when debugging. If you change the source asset or a preset while keeping a URL stable, plan for cache invalidation and verify when viewers receive the new output. A stable URL does not guarantee that every cache already contains the image or that it will retain it permanently.
Measure bytes, request timing and the selected candidate
Check a change on the actual page. In the browser's Network panel, filter image requests and inspect the URL downloaded, transferred bytes, request priority and timing. Compare those findings with the image's rendered dimensions. Chrome's Network panel reference explains the available request details.
Keep test conditions consistent. A browser-cache hit is not comparable to a fresh download. Test with caching disabled when comparing transfer sizes, then check repeat visits separately. Record the viewport, display density and network conditions alongside the chosen candidate.
For a page with an important hero image, use the Performance panel or Lighthouse to check its LCP behavior. If the file gets smaller but LCP barely changes, inspect late discovery or rendering delays before reducing quality again. A page-performance score does not assess whether product details or text remain visually usable.
Apply the workflow to one placement
- Preserve the source and identify the image's role on the page.
- Measure the rendered slot at the layouts you support and decide whether the crop fits.
- Choose a small set of candidate widths that covers those slots and relevant display densities.
- Compare appropriate formats at those dimensions, including any required fallback.
- Test quality settings while holding the other choices constant.
- Wire the candidate URLs into responsive markup and set loading priority for the placement.
- Measure transferred bytes, the selected candidate and request timing under consistent conditions.
- Inspect the image in the page. Adjust the setting that caused any visible problem.
Keep a brief record of the chosen widths, format, quality setting and tested placement. Recheck it when the layout or source material changes. That gives the next image a tested starting point without treating one compression number as a permanent rule.
Keep going
Make the media library less work.
See how Vyso brings search, enrichment, cleanup, and delivery into one product.
Start free