Skip to content

Use actual widths for srcset descriptors of undersized images - #105

Open
jan-23 wants to merge 1 commit into
pelican-plugins:mainfrom
jan-23:fix-srcset-undersized-images
Open

jan-23 wants to merge 1 commit into
pelican-plugins:mainfrom
jan-23:fix-srcset-undersized-images

Conversation

@jan-23

@jan-23 jan-23 commented Oct 9, 2026

Copy link
Copy Markdown

Fixes #53

Problem

When a source image is narrower than a srcset entry's w descriptor (and upscaling is disabled), the generated derivative ends up narrower than declared — but the srcset still advertises the declared width. For a 1500px image with 1000w/2000w/3000w entries, the browser is told it can pick a 3000px image, while the file is actually 1500px.

Change

After processing each srcset entry, the actual width of the derivative is compared with its w descriptor (new helper get_srcset_descriptor()):

  • If the image is at least as wide as declared, the descriptor is kept as-is.
  • If it is narrower, the descriptor is replaced by the real width (e.g. 1500w instead of 2000w).
  • If that real width is already present in the srcset, the entry is omitted.

For the example from the issue the result is:

srcset="/large/1000w/img_b.jpg 1000w, /large/2000w/img_b.jpg 1500w"

This applies to responsive-image and both picture code paths. Density (x) descriptors are untouched, and if an image cannot be processed the declared descriptor is kept.

Differences from the proposal in the issue

  • Derivative files are still generated. The width of a derivative is only known after running its operations (which may crop, upscale, or be arbitrary callables), and the existing cache relies on the output file existing. Not writing duplicates would mean re-processing them on every build, or adding persistent state. Because nothing links to these files, I kept this PR minimal; happy to add pruning in a follow-up if you think it's worthwhile.
  • The original image is not added as a bare fallback. A srcset cannot mix a candidate without a descriptor with w candidates. The derivative listed with its real width serves the same purpose while preserving format conversion and other operations.

Tests

  • Unit tests for get_srcset_descriptor()
  • An end-to-end test with a real image (pelican-bird.jpg, 1024px wide) and scale_out … False entries up to 3000w
  • A <picture> test with a mocked undersized source
  • Existing HTML-generation tests now use a mock that returns each derivative's declared width, so their expectations are unchanged

README and RELEASE.md updated.

🤖 Generated with Claude Code

When a derivative image is narrower than its `w` descriptor (e.g. the
source image is too small and upscaling is disabled), advertise its real
width in the srcset instead, and drop entries that would duplicate a
width already listed. Applies to responsive images and picture sources.

Fixes pelican-plugins#53

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

This branch has not been deployed

No deployments
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.

responsive-image handling adds entries to srcset even if the source image is smaller

1 participant