Skip to content

fix: request the CSS width for Retina srcset entries and use it in sizes - #1177

Open
selul wants to merge 1 commit into
developmentfrom
bugfix/1111
Open

selul wants to merge 1 commit into
developmentfrom
bugfix/1111

Conversation

@selul

@selul selul commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Related issues: #1111, #1113

With Retina images on, the page profiler's 2x srcset candidates delivered twice their advertised width, and the sizes attribute got a second, doubled condition for the same breakpoint. Both came from the same value: the 2x entry carries its delivered width (for example 824, advertised as 824w) together with dpr: 2, and that width was used both as the URL's w and as the sizes slot.

What changed

Note

Only sites with Retina images on (off by default) and only profiler-generated 2x candidates are affected. Their URLs change once, so the CDN fetches those variants again. Fixing it in PHP also corrects the profiles already stored (they last up to 7 days), with no JS change.

Not in this PR: when a page already has a sizes attribute, enhance_existing_sizes() sorts the merged conditions by breakpoint descending, so the first max-width condition matches every smaller viewport and the rest are never used. That changes sizes on most profiled pages and deserves its own issue.

Tests

  • tests/test-srcset.php: with Retina on, a 2x entry's URL is w:412/dpr:2/h:300 … 824w (no w:824); two breakpoints with 1x and 2x entries give one condition each, (max-width: 480px) 300px, (max-width: 768px) 412px. Both fail on development. Mutations (URL or sizes with the delivered width, height not divided) each fail a test.

QA

  1. Turn on Retina images in WP Admin → Optimole → Settings, and keep the page profiler on.

  2. Open a page with large content images on a desktop browser, then reload it once the profile is stored.

  3. View the source of an image that got a generated srcset.

    Expect: each 2x-sized candidate URL has w:<half the descriptor>/dpr:2 (for example w:412/dpr:2 … 824w), and sizes has one max-width condition per breakpoint.

Verification (head 335e1b4d)

Check Result
PHPUnit, full suite, PHP 8.4 (WP 7.1.3) PASS: 366 tests (baseline 364 + 2 new)
tests/test-srcset.php run alone PASS: 37 tests
New tests on the development source FAIL (2 of 2)
phpcs, phpstan (build-only include errors excluded locally; CI builds assets first) PASS

Not proven

  • The delivered pixel size against the live CDN (the multiplier is inferred from the plugin's own dpr:2 / 2x usage).

🤖 Generated with Claude Code

With Retina images on, the page profiler stores a 1x and a 2x entry per
breakpoint. The 2x entry carries its delivered width (e.g. 824, advertised
as "824w") and dpr 2, and the CDN multiplies w by dpr, so the URL asked for
w:824/dpr:2 and delivered 1648px for an 824w candidate (#1111). The sizes
attribute also used that doubled width, so a breakpoint got two max-width
conditions, one with the 2x width (#1113).

The URL now asks for the CSS width (width / dpr) with the dpr, and the
sizes slot uses the CSS width, so the 1x and 2x entries give the same
condition and array_unique() keeps one. Doing this in PHP also corrects
profiles already stored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pirate-bot

Copy link
Copy Markdown
Collaborator

Plugin build for 335e1b4 is ready 🛎️!

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.

2 participants