How to Optimize Rich Media for Core Web Vitals
Find the rich media affecting Core Web Vitals, improve its loading and layout stability, and measure whether real users benefit.
To optimize rich media for Core Web Vitals, first identify the page’s actual Largest Contentful Paint (LCP) element. Make an important image or video poster discoverable early, serve an appropriately sized responsive asset, and reserve its layout space before it loads. Lazy-load below-the-fold media, not the LCP image. Then check field data to see whether the change improved real users’ experience.
Use these “good” Core Web Vitals thresholds as targets: LCP at or below 2.5 seconds, Interaction to Next Paint (INP) at or below 200 milliseconds, and Cumulative Layout Shift (CLS) at or below 0.1. Evaluate the 75th percentile separately for mobile and desktop. web.dev’s Web Vitals guidance explains the metrics and thresholds.
1. Find the metric and media element causing the problem
Do not assume every large image is responsible for a slow page. LCP measures loading, INP measures responsiveness, and CLS measures visual stability. A video may contribute through its poster or first frame; an image, CSS background, or text block may be the actual LCP candidate. The candidate can differ by viewport and visit. Start with field data segmented by page or template, device class, and metric, then inspect a representative page with lab diagnostics.
- LCP is poor: identify the LCP element and investigate when its request begins, how long the resource takes to transfer, and when it renders.
- CLS is poor: look for images, video, embeds, ads, and iframes that acquire dimensions or get inserted after surrounding content has rendered.
- INP is poor: check scripts and interaction-heavy features, including media players and third-party widgets. Reducing image bytes alone may not fix responsiveness.
Lab tools help isolate causes under controlled conditions; they cannot represent the full range of real devices, networks, other running processes, and user interactions. Use field data to assess whether changes help users. See the LCP overview and the Web Vitals guide.
2. Make the LCP resource discoverable early
For an LCP image, put its URL in the initial HTML using src or srcset where possible. An image added later by JavaScript or discovered only after a script runs may start loading too late. If the LCP is a CSS background image, consider whether an ordinary image element better fits the content; where discovery remains delayed, assess whether an explicit preload is appropriate.
<img
src="/images/hero-1280.webp"
srcset="/images/hero-640.webp 640w,
/images/hero-1280.webp 1280w,
/images/hero-1920.webp 1920w"
sizes="(max-width: 700px) 100vw, 1200px"
width="1200"
height="675"
fetchpriority="high"
alt="A team reviewing a dashboard"
>
Use fetchpriority="high" as a targeted browser hint for an important image when measurement supports it. It is not a replacement for making the resource discoverable or checking field results. Do not add high priority to every image: competing high-priority requests can undermine the intent of prioritization. For preload, make sure the preloaded URL and responsive candidate match the resource the page will use, or the browser may fetch an unnecessary duplicate.
Do not apply loading="lazy" to the LCP image. Lazy loading delays the fetch until the browser determines the image is near the viewport. It is useful for below-the-fold images, provided their space is reserved. See web.dev’s LCP optimization guidance.
3. Serve responsive images at the size the page needs
Use srcset to provide width-based candidates and sizes to describe the image’s rendered width at different viewport sizes. The browser can then choose a suitable resource. Make the candidates correspond to real available files and describe the layout accurately; an incorrect sizes value can make the browser choose an oversized file or an image that looks soft.
<img
src="/images/article-960.webp"
srcset="/images/article-480.webp 480w,
/images/article-960.webp 960w,
/images/article-1440.webp 1440w"
sizes="(max-width: 600px) 100vw,
(max-width: 1000px) 90vw,
960px"
width="960"
height="640"
loading="lazy"
alt="A diagram of a responsive image workflow"
>
That example is for an offscreen article image; remove loading="lazy" if the image is the LCP candidate. The web.dev guide says serving desktop-sized images to mobile devices can use 2–4x more data than needed. That is a general estimate, not a guaranteed saving for every page. Read the responsive images guide for more on candidate selection.
For art direction, where the composition or crop should change across breakpoints, use <picture> with <source media> and provide an appropriate fallback <img>. Keep the reserved dimensions or aspect ratio consistent with the selected crop. Choose image formats and compression based on the browsers and quality requirements you support; inspect the rendered result at the size users see rather than judging only by file size.
4. Reserve space for images, video, and embeds
Include the intrinsic width and height of images and video so the browser can calculate an aspect ratio before the file loads. CSS can also reserve a box with aspect-ratio. Set dimensions that reflect the displayed crop; reserving the wrong ratio can still cause a shift when the media is laid out.
<video
controls
width="1280"
height="720"
poster="/media/intro-poster.webp"
>
<source src="/media/intro.webm" type="video/webm">
<source src="/media/intro.mp4" type="video/mp4">
</video>
<div class="video-embed">
<iframe src="https://example.com/embed/video"
title="Product overview"
loading="lazy"></iframe>
</div>
.video-embed {
aspect-ratio: 16 / 9;
width: 100%;
}
.video-embed iframe {
border: 0;
width: 100%;
height: 100%;
}
Reserve space for delayed embeds, ads, and iframes as well as first-party media. If third-party content has unpredictable dimensions, give it a container that limits how much it can move visible content. web.dev recommends including size attributes on images and video; see Optimize Cumulative Layout Shift.
5. Lazy-load only media that starts offscreen
Native lazy loading is a straightforward option for images below the fold. Use it selectively: the browser should not have to wait for a lazy-loading script to discover ordinary offscreen image URLs, and the page should still reserve each image’s dimensions. Avoid lazy loading content likely to appear in the initial viewport, especially the LCP candidate.
For video, choose loading behavior based on the experience. A poster can provide a visual placeholder, while a player or embed may bring substantial resources and scripts. Reserve the player’s space whether it loads immediately or later. If users do not need an embedded player until they interact, a lightweight placeholder can avoid loading third-party code early; measure both the impact on responsiveness and the user experience.
6. Check scripts and widgets when INP is the issue
Images mostly affect loading and transfer, but media players, consent tools, chat widgets, and other plugins can add JavaScript work. If INP is poor, determine whether a particular interaction or third-party feature delays the response. Review unused widgets and plugins and remove ones the page no longer needs. Optimizing the image file will not necessarily resolve a main-thread bottleneck. See web.dev’s guidance on optimizing Core Web Vitals.
7. Re-measure changes with field data
- Record the affected template, device segment, and failing metric before changing the page.
- Use a lab run to locate the LCP candidate, inspect resource discovery and size, and identify layout shifts or interaction delays.
- Change one relevant part of the loading path or layout at a time where practical: discovery, priority, responsive candidate, or reserved space.
- Repeat the lab check to catch regressions and confirm the intended element changed.
- Review field data for the same page or template and metric, separately for mobile and desktop, at the 75th percentile.
A better lab result is useful diagnostic evidence, but it does not prove that real users improved. Field data reflects variation across actual devices, networks, and interactions. Core Web Vitals thresholds and their rationale are described in web.dev’s threshold guidance.
8. Troubleshooting common rich-media problems
| Symptom | Likely cause | What to check or change |
|---|---|---|
| LCP image starts late | The URL is injected by JavaScript, hidden behind a script, or lazy-loaded. | Expose the resource in initial HTML, remove lazy loading from the LCP image, and consider a measured priority hint or preload when discovery is delayed. |
| Mobile LCP remains slow despite a fast connection | The browser is downloading a desktop-sized rendition. | Inspect the selected candidate and rendered width. Correct srcset and sizes and provide an appropriate smaller asset. |
| Image looks blurry or the wrong crop appears | Candidate widths, sizes, or art-direction breakpoints do not match the layout. |
Inspect the selected URL at each breakpoint and adjust candidates or use <picture> for distinct crops. |
| Content jumps when an image appears | Dimensions are missing or do not match the selected image’s aspect ratio. | Add accurate width and height attributes or reserve the correct aspect-ratio. |
| Page shifts when an embed or ad loads | The third-party content is inserted without a reserved box, or its final size differs. | Reserve a predictable container before loading it and constrain variable content to that box. |
| INP is poor but image compression changed nothing | Script execution or an interaction-heavy player/widget is delaying responses. | Inspect the affected interaction and its scripts; remove unused widgets or reduce unnecessary work. |
| Lab score improved, field data did not | The lab scenario may not match affected users, or the change may not address the field bottleneck. | Compare the same template, metric, and device segment in field data; verify the real LCP element and interaction conditions. |
9. Performance, reliability, and cost considerations
Responsive delivery can reduce bytes for devices that need a smaller rendition, but it depends on correct candidates, accurate layout hints, and usable image variants. Lazy loading can defer offscreen transfer, but applying it to the LCP resource can delay the page’s main content. Reserving space improves stability only when the reserved ratio reflects the eventual media.
Third-party embeds and widgets add dependencies outside the image itself. Their scripts and loading behavior can affect responsiveness or layout, so reserve space and measure the interaction path. Verify changes in both lab and field data; a single controlled run is not a reliable estimate of every visitor’s experience.
These optimizations are implemented in page markup, styles, media assets, and loading behavior. This research does not establish a particular paid image service or monitoring provider as necessary. Start with the resources and field measurements already available to your team, and evaluate any additional service against the actual bottleneck and its cost.
Or skip the browser setup
For screenshots used in visual checks, documentation, or workflows, ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF. It does not replace field Core Web Vitals measurement, but it can capture pages without maintaining your own browser capture setup. 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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, and failed loads are never billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Every feature is on every plan.
Sign up free for 1,000 screenshots a month, with no card required.
FAQ
Should I preload every image above the fold?
No. Identify the actual LCP resource and use preload only when it is discovered too late through normal HTML processing. Broad preloading can compete with other important requests.
Does a video always count as the LCP element?
No. A video’s poster or first frame can be the candidate, but the page’s largest qualifying content may instead be an image, background, or text. Confirm the candidate for the viewport and page state you are investigating.
Can a page pass Core Web Vitals in a lab run?
A lab run can help diagnose and validate changes under a controlled setup. The assessment of real-user experience depends on field data, including the 75th percentile for mobile and desktop.


