close
Skip to content

Prevent images from appearing squished when only one dimension is set#70575

Merged
ramonjd merged 2 commits into
WordPress:trunkfrom
lschuyler:fix/squishy-images-in-editor
May 15, 2026
Merged

Prevent images from appearing squished when only one dimension is set#70575
ramonjd merged 2 commits into
WordPress:trunkfrom
lschuyler:fix/squishy-images-in-editor

Conversation

@lschuyler
Copy link
Copy Markdown
Contributor

@lschuyler lschuyler commented Jul 1, 2025

This PR addresses the issue of images in the editor appearing squashed when only one dimension is set.

Problem

When you set only one of the image block's dimensions (width or height) in the editor and leave the other blank (auto), Gutenberg serializes just that single value as an inline style, like this:

<img 
  src="…blue-shape.png" 
  alt="blue-shape.png" 
  style="width: 64px;" 
  width="228" 
  height="228" 
/>

In this example, the blue-shape.png image was uploaded at 228 x 228. In the block editor UI, the width was set to 64px, and the height was left as auto.

Because many themes (like the one we were using when we discovered this) still define a fixed CSS height (in our case, 76px), the browser will render the image at 64 x 76, making it appear distorted.

In this example, this was the existing CSS:

.is-style-features-page-three-column-block_img img {
  width:  76px;
  height: 76px;
}

This Fix

This PR adds similar logic in two places to ensure that whenever only one dimension is set by the user, the other dimension is explicitly set to auto, to preserve the aspect ratio.

This logic is added in two places:

  1. Editor rendering (packages/block-library/src/image/image.js)
  2. Front-end save output (packages/block-library/src/image/save.js)

In each file, a small style object is built that:

  • Emits width: XXpx only if the user explicitly provided a width.
  • Emits height: auto when height is unset or explicitly set to "auto", blocking any theme CSS height.
  • Emits height: XXpx only when the user set a numeric height.

By guaranteeing height: auto whenever height isn't defined, this prevents themes' CSS heights from squashing the image. A theme's default width remains in effect when the user hasn't adjusted the width in the editor.

Handling Existing Content

A new deprecation (v9) is added to handle image blocks that were saved before this fix with only width set and no height in the inline style. When one of those blocks is next saved, it will be migrated so the inline style includes height: auto. Integration test fixtures are included covering parse and serialisation of this migration path.

Testing Instructions

  1. Before you put this PR in place, go to Appearance -> Editor -> Design -> Styles -> CSS and add a new style definition for the image you are about to add:
.image-test img {
	width: 76px;
	height: 76px;
}
  1. Create a new page.
  2. Insert an image block (select any image from your Media Library) and set the width to a number (example 64) and leave the height blank.
  3. While that image is still selected, expand "Advanced" and add the image-test class.
  4. Notice the image dimensions. Save the page and view it (outside of the editor). Right click and select "Inspect" to see the inline style. The image will appear compressed.
  5. Put this PR in place and try resetting the dimensions in the editor UI again for this image by setting the width to 50 and leaving the height unset (or set to auto).
  6. Repeat step 5. This time, the image won't appear compressed.

Screenshots (inside the Editor)

Before the fix (64 x 76):
Screenshot 2025-06-30 at 9 44 24 PM

After the fix (64 x 64):
Screenshot 2025-06-30 at 9 45 15 PM

@lschuyler lschuyler requested a review from artemiomorales as a code owner July 1, 2025 05:20
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jul 1, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: lschuyler <lschuyler@git.wordpress.org>
Co-authored-by: aaronrobertshaw <aaronrobertshaw@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@lschuyler lschuyler marked this pull request as draft July 1, 2025 05:36
@lschuyler lschuyler marked this pull request as ready for review July 1, 2025 06:27
@t-hamano t-hamano added [Type] Bug An existing feature does not function as intended [Block] Image Affects the Image Block labels Jul 1, 2025
@youknowriad youknowriad requested review from a team, Mamaduka, adamziel, draganescu and michalczaplinski and removed request for a team July 1, 2025 14:48
@lschuyler lschuyler force-pushed the fix/squishy-images-in-editor branch from 3142a24 to e81e430 Compare March 7, 2026 00:12
@github-actions github-actions Bot added the [Package] Block library /packages/block-library label Mar 7, 2026
@lschuyler
Copy link
Copy Markdown
Contributor Author

Update after rebasing on trunk.

This has been rebased and reworked since the original submission. Main changes:

  • The fix is now conditional — height: auto is only applied inline when width is set and height is not (and vice versa), rather than always writing both dimensions.
  • A v9 deprecation has been added so that existing posts with only width set are migrated correctly on re-save rather than triggering a block validation error.
  • Integration test fixtures are included for the deprecation path.

Copy link
Copy Markdown
Contributor

@aaronrobertshaw aaronrobertshaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the work on this @lschuyler 👍

This is testing pretty nicely for me.

For others looking at the deprecation, it's worth noting that the structure in this PR is correct. As older deprecations would match on their outdated markup, they'd get resaved to acquire the height: auto inline style as needed. Given there is no migration of attributes required, only the new v9 deprecation is needed.

While reviewing the deprecations I think I spotted one issue with v7.migrate(). With the unconditional template literal, a block with width: 300, height: undefined migrates to height: "undefinedpx". The new current save() then serializes that literally as style="height: undefinedpx".

The v6.migrate() function handles this better.

The bug there predates this PR but this one does make it worse. So I think we should fix it up now. Additionally, it's just nice whenever adding a new version for a block to ensure every past version is migrated correctly to the latest and greatest.

One other thing, is the isEligible check actually needed? It's conventionally for attribute schema only migrations where the block markup is technically still valid but the attributes still need migrating. I feel isEligible here might be redundant and slightly misleading.

More practically: after a block is migrated and re-saved with the new format, the height attribute is still undefined (it's never stored), so isEligible would keep returning true on every subsequent load. With no migrate() this is a no-op, but it means the deprecation system needlessly processes the block on every parse. Worth dropping isEligible from v9 entirely since the save() match handles it.

@lschuyler
Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review @aaronrobertshaw! I pushed another commit to address your feedback:

  • Fixed v7.migrate() to guard with typeof width === 'number' before appending 'px', matching the pattern already used in v6.migrate().
  • Removed isEligible from v9. You're right, that it was redundant and would have caused unnecessary reprocessing on every parse.

Copy link
Copy Markdown
Contributor

@aaronrobertshaw aaronrobertshaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tweaks to the deprecations look good, thanks @lschuyler 🚀

This PR is testing as advertised for me.

Before After
Image Image

LGTM 🚢

lschuyler added 2 commits May 14, 2026 13:59
When a user sets only a width (or only a height) on an image block,
theme CSS can override the other dimension and squish the image.
This change sets the unspecified dimension to `auto` via inline style
so it takes precedence over any theme stylesheet.

A v9 deprecation is added so that images saved without the explicit
`height: auto` are still recognized as valid and migrated on the next
save.
…gible

v7.migrate() was unconditionally wrapping width and height in template
literals, producing "undefinedpx" when either dimension was not set.
Match the safer pattern used in v6.migrate(), which guards with
typeof ... === 'number' before appending 'px'.

Remove isEligible from v9. Since height is never stored in block
attributes when left unset, isEligible would return true on every parse
of a block with only width set, causing the deprecation system to
needlessly reprocess it. The save() match handles detection correctly
without isEligible.
@lschuyler lschuyler force-pushed the fix/squishy-images-in-editor branch from ff94bca to 538fea2 Compare May 14, 2026 21:00
@youknowriad
Copy link
Copy Markdown
Contributor

@aaronrobertshaw any reason this was not merged when the PR was approved?

@ramonjd
Copy link
Copy Markdown
Member

ramonjd commented May 15, 2026

I just re-tested this. Thanks for rebasing @lschuyler

It's working well for me. I can merge it.

@ramonjd ramonjd merged commit 48411f0 into WordPress:trunk May 15, 2026
39 checks passed
@github-actions github-actions Bot added this to the Gutenberg 23.3 milestone May 15, 2026
@aaronrobertshaw
Copy link
Copy Markdown
Contributor

@aaronrobertshaw any reason this was not merged when the PR was approved?

Apologies for the slow reply while away. I have a vague recollection of re-running a failed test. Looks like I missed hitting auto merge 😬

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

Labels

[Block] Image Affects the Image Block [Package] Block library /packages/block-library [Type] Bug An existing feature does not function as intended

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants