Skip to content

Serve 2x assets on retina screens via srcset#1058

Closed
PavelMakarchuk wants to merge 1 commit into
mainfrom
fix/optimised-image-retina-srcset
Closed

Serve 2x assets on retina screens via srcset#1058
PavelMakarchuk wants to merge 1 commit into
mainfrom
fix/optimised-image-retina-srcset

Conversation

@PavelMakarchuk
Copy link
Copy Markdown
Contributor

Summary

  • Images across the site appear soft/blurry on retina and high-DPI displays. Cause: OptimisedImage hardcoded dpr = 1, so an image asked to fill (say) a 640px slot was fetched at 640px of pixel data and then upscaled by the browser to ~1280 physical pixels on every modern laptop and phone.
  • Adds a 1x/2x srcset so the browser picks the right asset per device. Low-DPI screens keep using the 1x file (no bandwidth waste); high-DPI screens get the sharper 2x.
  • When the snapped 1x and 2x widths collide on the same ALLOWED_WIDTHS bucket (e.g. width=1080 → 2x snaps to 1920, but width=1200 → 2x also snaps to 1920 → same as 1x at the next-higher bucket in some configurations), the srcset descriptor is dropped to avoid the browser double-fetching identical files.
  • Factored bypass conditions (external URLs, SVGs, /_next/*, dev mode, missing width) into shouldSkipOptimisation() so the main render branch reads as straight srcset construction.

Affected surfaces

Every consumer of OptimisedImage — including:

  • Home hero, blog preview cards, tracker preview
  • Team page photos
  • Research grid and post hero images
  • Events page card images
  • Citations grid

Test plan

  • Load /us on a retina display and confirm the hero photo and blog preview cards render sharply (compare to before this PR)
  • Open devtools → Network → Img and confirm requests now include &w= values at ~2× the rendered width
  • Confirm low-DPI window (devtools device emulation with DPR=1) still requests the smaller w= value
  • Confirm SVGs, external URLs, and /_next/* paths still fall through unchanged

🤖 Generated with Claude Code

OptimisedImage hardcoded dpr = 1, so an image asked to fill a 640px slot
was fetched at 640px and then upscaled by the browser to ~1280 physical
pixels on every retina/high-DPI display — visibly soft across hero,
team photos, blog/research cards, and tracker thumbnails.

Switches to a 1x/2x srcset: the browser picks the right asset per
device. Low-DPI screens keep using the 1x file (no bandwidth waste),
high-DPI screens get the sharper 2x. When the snapped 1x and 2x widths
collide (e.g. both round to the same ALLOWED_WIDTHS bucket) we drop the
descriptor so the browser doesn't double-fetch the same file.

Also factored out the bypass conditions into shouldSkipOptimisation()
so the main render branch reads as straight srcset construction.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
policyengine-app-v2 Ready Ready Preview, Comment May 26, 2026 12:50pm
policyengine-calculator Ready Ready Preview, Comment May 26, 2026 12:50pm
policyengine-calculator-next Ready Ready Preview, Comment May 26, 2026 12:50pm
policyengine-website Ready Ready Preview, Comment May 26, 2026 12:50pm

Request Review

@PavelMakarchuk
Copy link
Copy Markdown
Contributor Author

Folding into #1056 per request — both changes affect home page render quality.

@PavelMakarchuk PavelMakarchuk deleted the fix/optimised-image-retina-srcset branch May 26, 2026 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant