Skip to content

Make data-sizes="auto" object-fit aware#3

Open
JonatanStorlund wants to merge 1 commit into
masterfrom
fix/object-fit-auto-sizes
Open

Make data-sizes="auto" object-fit aware#3
JonatanStorlund wants to merge 1 commit into
masterfrom
fix/object-fit-auto-sizes

Conversation

@JonatanStorlund

Copy link
Copy Markdown
Member

Problem

Lazyloaded images using data-sizes="auto" had their sizes resolved purely from the element's offsetWidth in the lozad loaded handler:

element.sizes = sizes === 'auto' ? (width ? `${width}px` : '100vw') : sizes

For images rendered with object-fit: cover / object-fit: contain — e.g. fill images in core/media-text blocks (is-image-fill-element, which WP core styles with object-fit:cover;width:100%;height:100%) — the painted image is scaled to cover/fit a box with a different aspect ratio than the source. The box width therefore underestimates the number of pixels actually painted, so the browser selects a too-small srcset candidate and the image looks blurry.

On a real page this resolved to e.g. sizes="660px" (the box width) for a 2560×1708 image filling a tall column, when ~1300px were actually needed.

Themes worked around this by computing a custom sizes and skipping lazyload for those images. This should just work out of the box.

Fix

When resolving data-sizes="auto", take the image's object-fit into account:

  • Default (fill/none) → keep using offsetWidth (unchanged behavior).
  • covermax(offsetWidth, offsetHeight * aspectRatio)
  • containmin(offsetWidth, offsetHeight * aspectRatio)

The intrinsic aspect ratio is read from the width/height attributes (always present, so it works before the image has decoded), falling back to the decoded dimensions.

Result

The same fill image now resolves to sizes="1343px" and picks a sharp candidate — with no theme-side sizes/skip-lazyload workarounds.

Test plan

  • npm run build:production (bundle regenerated and committed)
  • Verified in headless Chrome on a real page: the media-text fill image resolves from 660px1343px with no theme overrides active
  • Sanity check normal (non-object-fit) lazy images are unchanged

Made with Cursor

Lazyloaded images using `data-sizes="auto"` resolved `sizes` from the
element's `offsetWidth`. For images rendered with `object-fit: cover` or
`object-fit: contain` (e.g. fill images in core/media-text blocks) the
painted image is scaled to cover/fit a box with a different aspect ratio,
so the box width underestimates the pixels actually needed and the browser
picks a too-small, blurry srcset candidate.

Account for the object-fit by deriving the effective width from the box
dimensions and the image's intrinsic aspect ratio (read from the width/height
attributes so it works before the image has decoded). Default object-fit
(`fill`) keeps using `offsetWidth` as before.

This fixes blurry object-fit fill images out of the box without per-theme
`sizes`/skip-lazyload workarounds.

Co-authored-by: Cursor <cursoragent@cursor.com>
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