Skip to content

Generated sizes attribute can contain duplicate max-width conditions #1113

Open

Description

@pirate-bot

Status (2026-10-11)

Fixed in PR #1177 (bugfix/1111 → development, approved by pirate-bot at 13fb6a0d). The PR fixes #1111 and #1113 together; they come from the same value.

  • Fix: The sizes attribute now gets one max-width condition per breakpoint. The 2x entry used its doubled width as a second slot for the same breakpoint; both entries now use the CSS width, so the duplicate is dropped.
  • Scope: only sites with Retina images on, and only profiler-generated 2x candidates. Stored profiles are corrected too, with no JS change.
  • Tests: two new tests in tests/test-srcset.php, failing on development.
  • Not proven: the pixel size the live CDN delivers (the multiplier is taken from the plugin's own dpr:2 / 2x usage).

Summary

With Retina Quality enabled, Optimole can emit multiple sizes clauses using the same max-width condition but different slot widths. Each breakpoint is expected to have an unambiguous effective slot declaration. Because only the first matching condition participates in browser selection, later duplicates are unreachable and can leave the browser using an unintended slot width.

Customer context

Product / area: Optimole page profiler and generated sizes attributes
Version: Customer version not provided; inspected source is v4.2.10
Environment: Responsive WordPress frontend with Retina Quality enabled
Integration / third party: Browser responsive-image selection
Reported error / symptom: Duplicate conditions such as two max-width: 768px entries
Impact: Conflicting responsive-image metadata can cause unintended candidate selection and oversized downloads.

Reproduction notes

Confirmed by direct code inspection and by support's inspection of the reported output; no local browser reproduction was performed.

  1. Enable Retina Quality for an image eligible for page-profiler-generated responsive candidates.
  2. Allow both 1x and 2x candidates for one breakpoint to survive candidate selection and filtering.
  3. Inspect the generated sizes attribute on a later rendered response.
  4. Observe repeated conditions such as (max-width: 768px) paired with different slot widths.

Diagnosis

Conclusion

The profiler generates 1x and 2x resource candidates for the same breakpoint, multiplies each candidate's width by DPR, and carries both into PHP. PHP then uses each resource width as the CSS slot width for that shared breakpoint. Deduplication compares complete strings, so clauses with the same condition and different widths remain. The behavior is deterministic when both density candidates survive selection and filtering.

Where this likely occurs

  • assets/js/modules/srcset-detector.js — optmlSrcsetDetector._generateResponsiveSizes() lines 419–460 iterates both DPR multipliers for each breakpoint and assigns the same breakpoint to differently scaled widths.
  • assets/js/modules/srcset-detector.js — optmlSrcsetDetector._selectBestVariations() lines 531–585 intentionally retains selected 1x and 2x entries and deduplicates by resource width rather than breakpoint.
  • inc/tag_replacer.php — Optml_Tag_Replacer::add_missing_srcset_attributes() lines 487–517 creates a sizes clause from every retained candidate using the DPR-scaled width.
  • inc/tag_replacer.php — Optml_Tag_Replacer::add_missing_srcset_attributes() lines 553–578 applies array_unique() to complete clause strings, preserving same-breakpoint clauses with different widths.
  • inc/tag_replacer.php — Optml_Tag_Replacer::enhance_existing_sizes() lines 647–676 has the same complete-string deduplication behavior when extending an existing simple sizes value.
  • Commits 8ab74741721c and 49a757f34fd1 introduced the relevant profiler and generation path; the behavior remains in inspected v4.2.10.

Engineering notes

The path is primarily reachable with Retina Quality enabled because add_missing_srcset_attributes() filters out entries with DPR greater than one when the setting is disabled. Both candidates also have to survive natural-dimension validation, the variation limit, and container filtering. The duplicate clauses represent resource-density alternatives as CSS slot alternatives, although a sizes media list resolves the first matching condition rather than selecting among conditions by DPR.

Test coverage status

tests/test-srcset.php lines 112–169 and 211–224 cover distinct breakpoints only. assets/js/modules/__tests__/srcset-detector.test.js covers retention of 1x and 2x candidates but does not inspect rendered same-breakpoint sizes clauses. No relevant test found during inspection supplies density variants sharing a breakpoint and checks condition uniqueness. Tests were not executed during this read-only investigation.

What to verify or explore next

  • Reproduce with Retina Quality enabled and an image large enough for both density candidates to survive validation.
  • Inspect generated sizes output for repeated media conditions and record which clause appears first.
  • Compare selected resources before and after profile data is stored.
  • Run the targeted PHP srcset suite and JavaScript srcset-detector suite across images with and without existing simple sizes attributes.

Unknowns / follow-up

The exact ordering observed on the customer's page and the customer plugin version are unknown.

Confidence

Confidence: 97/100

Repository inspection confirms three independently verifiable defects in Optimole's page-profiler responsive-image path, and no matching GitHub issues were found. The reported Retina-disabled 1x behavior is intentional setting behavior covered by tests, so it is not included as a defect.


Source: HelpScout #3424946418
Generated by bug-report-triage (ID: bug-report-triage_6a87087cc5e402.90677248)

Activity

  1. added theissue type on Aug 20, 2026
  2. self-assigned this
    on Oct 9, 2026
  3. milicavs commented on Oct 11, 2026

    @milicavs

    🧪 QA steps and test sandbox

    With Retina images on, the sizes attribute Optimole adds to profiled images lists the same screen width twice with two different image widths, for example (max-width: 768px) 412px, (max-width: 768px) 824px. Browsers only use the first match, so the second entry is dead weight and the image size the browser picks can be wrong.

    Requires: your own Optimole account (API key), since Optimole only rewrites images on a connected site.

    Step Build Bot check
    Reproduce the bug Optimole 4.2.16 (released) ⏭️ Not checked: needs an Optimole account
    Verify the fix PR #1177 build 13fb6a0 ⏭️ Not checked: needs an Optimole account

    On the sandbox:

    • https://qa-optimole-wp-1113.s1-sandywp.com runs the release. Sign in to SandyWP and use the sandbox's Auto Login.
    • Step 2 is already done, and the Retina test page has three large images (2400, 2000 and 1800px wide).
    • Tools → QA Logs shows debug.log, which the public site can't read.
    • If it has stopped after a day without use, the next qa-playground run brings it back.

    Reproduce on Optimole 4.2.16:

    1. Optimole → connect with your API key.
    2. Optimole → Settings: make sure Retina images is on, then save.
    3. Open /?pagename=retina-test on a desktop browser and wait a few seconds, so Optimole profiles the page.
    4. Reload the page, then view the page source and read the sizes attribute of an image that got a generated srcset.
    • Bug: the same (max-width: …px) condition appears twice, once with a width and once with double that width.
    • Fixed: each (max-width: …px) condition appears once, with the smaller (CSS) width.

    Verify the fix on the same sandbox:

    1. Download the PR build above, then go to Plugins → Add New Plugin → Upload Plugin and click Replace current with uploaded.
    2. Repeat the steps above from step 3.
    • Fixed: as above. Plugins still shows 4.2.16, since the build has no version bump.
    Edge cases
    • Retina images off: sizes has one condition per breakpoint, same as before.
    • The srcset still lists both the 1x and the 2x candidate for each breakpoint.
    • A page profiled before the update: after the update, reloading it gives the deduplicated sizes without re-profiling.
    • An image whose block already had a sizes attribute: it still renders, with no duplicate conditions added.

    Fix: #1177 (open, also fixes #1111)

  4. pirate-bot commented on Oct 11, 2026

    @pirate-bot
    CollaboratorAuthor

    QA agent — 🟢 Passing checks · Retina sizes are deduplicated, including profiles saved before the update.

    Using a seeded connected account and local image delivery, the Retina setting survived save and reload. Fresh and pre-update profiles produced unique CSS-width clauses and correct Retina URL dimensions; the base build reproduced the duplicates. Retina-off output kept only 1x candidates, and the edge matrix passed. Both added tests passed on the candidate and failed on the base. Live CDN pixel dimensions were not verified.

    Worth a human look

    1. Verify the live CDN returns the advertised pixel widths and heights for profiler 2x URLs using a real Optimole account.
    2. Check viewport selection for images with pre-existing simple sizes; their merged clauses still use descending breakpoint order, as noted outside PR fix: request the CSS width for Retina srcset entries and use it in sizes #1177.
    3. Check profiler srcset generation for native-lazy-loaded images below the fold; the initial third image had no generated srcset, while the regular replacement path passed.
    Checks (5 passed)
    • ✅ Saving Retina images as enabled in Optimole Settings persists after reloading, with the page profiler enabled.
    • ✅ After desktop page profiling stores 1x and 2x candidates and the page is reloaded, generated sizes has one max-width condition per breakpoint using the CSS slot width.
    • ✅ Profile-generated Retina candidate URLs request CSS width and height with dpr:2 while retaining the advertised delivered-width descriptors and 1x alternatives.
    • ✅ Installing the candidate over profiles saved by qa-base corrects generated sizes and Retina URLs without re-profiling, including images with an existing simple sizes attribute.
    • ✅ With Retina images disabled and saved, reloading the profiled page keeps 1x candidates and single CSS-width sizes conditions while excluding profiler 2x candidates.

    Full report, evidence and session trail

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions