How to Make Website Thumbnails with Lazy-Loaded Hero Images
Build sharp, responsive website thumbnails without stretching or layout shifts, and load hero images at the right time.
To make website thumbnails, create image variants sized for their display slots, reserve each slot’s aspect ratio, and choose whether to crop with object-fit: cover or show the full image with contain. Use srcset and sizes when the rendered width varies. Lazy-load below-the-fold thumbnails; load an initially visible hero image eagerly, especially when it is likely to be the Largest Contentful Paint (LCP) element.
Lazy loading only controls when the browser requests an image. It does not create a smaller thumbnail or define its crop.
1. Choose the thumbnail frame and crop
Start with the space the image must occupy in the design. Common card layouts use consistent frames, but there is no universally correct thumbnail size or aspect ratio: choose dimensions that match your actual layout and content.
- Use
coverwhen every card should fill the same frame. It preserves the image ratio and crops the overflow. - Use
containwhen viewers need to see the whole image. It can leave empty space inside the frame. - Set
object-positionto keep a face, product, or other focal point in view whencovercrops the edges.
Do not force an image into a different ratio by assigning unrelated width and height dimensions without a crop or containment rule; that stretches the image.
.story-thumbnail {
display: block;
width: 100%;
aspect-ratio: 3 / 2;
object-fit: cover;
object-position: center;
}
For a portrait subject that sits near the top of the source image, for example, try object-position: center 30% and review the result at the real card size.
2. Reserve space before the image loads
Give an <img> intrinsic width and height attributes matching the source ratio, or reserve the frame with CSS aspect-ratio. The browser can allocate the right amount of space before image data arrives, which helps prevent layout shifts.
When the CSS frame differs from the image’s ratio, pair the frame with object-fit. Avoid sizing the image in a way that distorts its contents.
3. Generate and serve suitable image sizes
A thumbnail slot rarely needs the full original image. Generate smaller variants during upload or at build time for the sizes your layout uses. For example, an image pipeline can produce 300-pixel and 600-pixel-wide WebP files. The web.dev guidance names Sharp as one option for automating resized variants; the appropriate pipeline depends on your stack.
Use srcset to offer the browser multiple width candidates and sizes to describe the image’s expected rendered width at different viewport sizes. The browser can then choose an offered resource for the layout. Make sure each candidate actually has the width stated in srcset, and make the sizes expression match the page’s real breakpoints and columns.
<img
class="story-thumbnail"
src="/images/story-thumb-600.webp"
srcset="/images/story-thumb-300.webp 300w,
/images/story-thumb-600.webp 600w"
sizes="(min-width: 66em) 33vw, (min-width: 44em) 50vw, 100vw"
width="600"
height="400"
alt="A developer reviewing a page of image cards"
>
Here the 600-by-400 dimensions communicate a 3:2 ratio. Adapt the paths, available variants, dimensions, alt text, and sizes to the files and layout you actually serve.
4. Lazy-load offscreen thumbnails, not the visible hero
For images below the fold that can wait until a reader scrolls toward them, add loading="lazy". Browser heuristics decide when a lazy image is close enough to the viewport to request, so it may start loading before it becomes visible.
<img
src="/images/story-thumb-600.webp"
srcset="/images/story-thumb-300.webp 300w,
/images/story-thumb-600.webp 600w"
sizes="(min-width: 66em) 33vw, (min-width: 44em) 50vw, 100vw"
width="600"
height="400"
loading="lazy"
alt="A developer reviewing a page of image cards"
>
Do not lazy-load a hero image that is visible at the initial page load and likely to be the LCP image. Leave off loading or use loading="eager"; consider fetchpriority="high" when that hero is the important LCP resource. web.dev’s guidance says: “Images that are highly likely to be in-viewport, and in particular LCP images, should not be lazy-loaded.” (web.dev: Browser-level image lazy loading for the web.)
<img
src="/images/hero-1200.webp"
srcset="/images/hero-800.webp 800w,
/images/hero-1200.webp 1200w"
sizes="100vw"
width="1200"
height="800"
loading="eager"
fetchpriority="high"
alt="A description of the hero image"
>
Use fetchpriority="high" selectively for an important image that should be discovered promptly. Confirm the browser’s resource priority and whether the image is actually the LCP element instead of applying high priority to every image.
5. Check the page at real viewport sizes
- Inspect the card and hero at the viewport widths where the layout changes.
- Confirm thumbnails fill or contain their frames as intended, and that the subject remains visible in each crop.
- Check that the width and height attributes preserve the intended ratio and that the page reserves space before images load.
- Inspect which responsive candidate the browser selected and whether offscreen images are deferred.
- For performance work, evaluate lab and field performance. A markup change alone does not establish a specific LCP improvement.
6. Common problems and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Thumbnail looks stretched | The rendered frame and image ratio differ without a crop or containment rule. | Set a deliberate frame ratio and use object-fit: cover or contain. |
| Important subject is cut off | cover crops the source around the default focal point. |
Adjust object-position, change the crop, or use contain if the whole image must remain visible. |
| Content jumps when images appear | The browser has no early indication of the image’s dimensions or frame ratio. | Provide matching width and height attributes or reserve space with aspect-ratio. |
| Thumbnail downloads an unnecessarily large source | Only a large source is offered, or srcset/sizes do not reflect the layout. |
Generate appropriately sized variants and offer them with accurate width descriptors and sizes. |
| Visible hero appears late | It is lazy-loaded even though it is visible at initial load, or its request is not prioritized appropriately. | Remove lazy loading or set eager loading; consider high fetch priority if it is the LCP image. Verify how the browser discovers and prioritizes the resource, especially for CSS background images. |
| Below-fold images load too early or late | Lazy loading follows browser heuristics, and the image position or layout may not match expectations. | Confirm the element is genuinely below the fold and inspect request timing in the actual page. Lazy loading does not promise a fixed distance or time. |
| Browser keeps choosing the wrong candidate | The sizes value does not describe the image’s actual rendered width, or the width descriptor is inaccurate. |
Update sizes for the real layout and ensure each srcset descriptor matches its file width. |
7. Performance, reliability, and cost considerations
- Transfer and decoding: Smaller variants reduce the amount of image data a thumbnail may need, but the right dimensions and format depend on your content and delivery setup. The research does not establish a universal format, quality setting, or performance gain.
- Layout stability: Supplying dimensions or an aspect ratio lets the browser reserve space before download. Check the rendered page because CSS and markup both affect the final frame.
- Request timing: Lazy loading can defer below-fold requests. Applying it to an initially visible LCP hero can delay a resource the page needs promptly.
- Pipeline choices: Pre-generate variants during upload or build, or use a transformation service at delivery time. Choose based on your architecture; the available research does not compare commercial services.
- Reliability: Keep a valid fallback in
src, ensure all referenced variants exist, and review the page at its responsive breakpoints. A broken candidate can undermine otherwise correct responsive markup.
8. Or skip the browser setup
If your task is to capture a page as an image while checking its hero and thumbnail rendering, ScreenshotNeo is a website screenshot API and MCP server. A GET request returns a PNG, JPEG, WebP, or PDF; the API can also capture full pages and wait for a selector, delay, or network idle. 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}`);
ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits cost nothing, 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 a month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan.
Sign up for 1,000 free screenshots a month, with no card required.
FAQ
Does lazy loading make a thumbnail file smaller?
No. It changes when the browser requests an image. Generate smaller variants and offer them with responsive image markup to reduce the source size available for a slot.
Should a hero image be lazy-loaded?
If it is visible at initial load and likely to be the LCP image, do not lazy-load it. Use eager loading or the default loading behavior, and consider high fetch priority when appropriate.
How do I stop thumbnails from stretching?
Reserve a frame ratio and choose object-fit: cover to fill it by cropping, or contain to show the entire image.
Do all thumbnails need srcset?
It is useful when the same image appears at substantially different rendered widths and you can provide suitable alternatives. For a consistently sized slot, a single appropriately sized source may be sufficient.


