Reference guide · images · Published 2026-08-16 · 3 min read
Serving thumbnails fast
Serve thumbnails fast: generate the right size, use WebP/AVIF, cache immutably, add width and height, and lazy-load in grids.
- ·The size and the file
- ·The cache contract
- ·Layout and lazy
The thumbnail is a different asset, not a shrunken one
A thumbnail is a specific asset: a small image sized for its spot in a list or grid, generated once, stored separately. The fastest thumbnail service is the one that never asks a full-size image to the client: the browser downloads the 300px file for the 300px box, not the 2400px original scaled down by CSS. This single habit deletes most of the image weight a list page ships. The image optimisation guide covers the general format choices; the thumbnail adds the size, cache, and layout discipline.
Size and format
| Use | Typical size | Format |
|---|---|---|
| Card / grid thumbnail | 300-400 px wide | WebP or AVIF (photo) / PNG (logo) |
| Avatar | 64-128 px | WebP / AVIF |
| List image | 600-800 px | WebP / AVIF |
Pick sizes to match your responsive grid breakpoints, or generate 3-5 variants per thumb (256/512/768 px) and let the srcset system pick. The format should match the original content: a photographic thumbnail in WebP/AVIF; a logo or diagram in PNG/SVG (the format guide explains why SVG is not for photos).
The cache contract
Thumbnails are the easiest content to cache well because they change rarely:
- generate each thumbnail once (on upload, not per request), write to a
thumbs/folder or through the image CDN variant system; - serve with
Cache-Control: public, max-age=31536000, immutableplus a content-hash path, so re-generation creates a new URL instead of overwriting a cache; - re-generate on source change with an explicit flush or new name, exactly like the CDN static assets rule.
The worst pattern: theme-level thumbnails that regenerate on the fly and cache with the URL of the original photo. That couples a variable page to a cache forever and produces stale grids after uploads.
Layout and lazy-loading
The layout shift and lazy loading rules apply to every thumbnail:
- Set
widthandheight(oraspect-ratio) on each<img>so the grid reserves space while the thumbs lazy-load. - Add
loading="lazy"to every thumbnail below the fold (keeping the first above-the-fold eagerly loaded as LCP allows). - Use
decoding="async"on below-the-fold thumbs so the browser does not block on decode.
Serve an appropriate-size thumbnail, always
The browser-side fallback when your template forgets: a 35px thumb sent to a 200px box shows up slightly soft but still fast; the reverse, a 2400px original sent to a 200px box, is the expensive mistake that makes grids slow and LCP hurt. A lint/grep for "width=2400 on a card" or the_image( 'large' ) in templates catches many of these during review.
Prevention
- Generate thumbnails on upload, not per request.
- Serve them from an immutable cached route with content-hash names.
- Use
srcsetfor the 2-3 sizes the layout needs and let the browser pick. - Reserve layout space and lazy-load below the fold.
That leaves a list page whose total image weight is a few hundred KB instead of several MB, and the web performance audit is the place to prove the before/after.