Skip to content

Commit

Permalink
Limit the max width of image to its container size (WordPress#63341)
Browse files Browse the repository at this point in the history
Co-authored-by: kevin940726 <[email protected]>
Co-authored-by: andrewserong <[email protected]>
Co-authored-by: talldan <[email protected]>
Co-authored-by: noisysocks <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: jasmussen <[email protected]>
* Limit the max width of image to its container size

* Try fixing e2e tests

* Snap to max width after resize

* Set to undefined instead

* Do not override aspect ratio
  • Loading branch information
kevin940726 authored Aug 26, 2024
1 parent dec82e2 commit c7c8c4b
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 31 deletions.
70 changes: 41 additions & 29 deletions packages/block-library/src/image/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { useEffect, useRef, useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
import { image as icon, plugins as pluginsIcon } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';
import { useResizeObserver } from '@wordpress/compose';

/**
* Internal dependencies
Expand Down Expand Up @@ -109,6 +110,9 @@ export function ImageEdit( {
} = attributes;
const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob );

const [ contentResizeListener, { width: containerWidth } ] =
useResizeObserver();

const altRef = useRef();
useEffect( () => {
altRef.current = alt;
Expand Down Expand Up @@ -364,35 +368,43 @@ export function ImageEdit( {
};

return (
<figure { ...blockProps }>
<Image
temporaryURL={ temporaryURL }
attributes={ attributes }
setAttributes={ setAttributes }
isSingleSelected={ isSingleSelected }
insertBlocksAfter={ insertBlocksAfter }
onReplace={ onReplace }
onSelectImage={ onSelectImage }
onSelectURL={ onSelectURL }
onUploadError={ onUploadError }
context={ context }
clientId={ clientId }
blockEditingMode={ blockEditingMode }
parentLayoutType={ parentLayout?.type }
/>
<MediaPlaceholder
icon={ <BlockIcon icon={ icon } /> }
onSelect={ onSelectImage }
onSelectURL={ onSelectURL }
onError={ onUploadError }
placeholder={ placeholder }
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
value={ { id, src } }
mediaPreview={ mediaPreview }
disableMediaButtons={ temporaryURL || url }
/>
</figure>
<>
<figure { ...blockProps }>
<Image
temporaryURL={ temporaryURL }
attributes={ attributes }
setAttributes={ setAttributes }
isSingleSelected={ isSingleSelected }
insertBlocksAfter={ insertBlocksAfter }
onReplace={ onReplace }
onSelectImage={ onSelectImage }
onSelectURL={ onSelectURL }
onUploadError={ onUploadError }
context={ context }
clientId={ clientId }
blockEditingMode={ blockEditingMode }
parentLayoutType={ parentLayout?.type }
containerWidth={ containerWidth }
/>
<MediaPlaceholder
icon={ <BlockIcon icon={ icon } /> }
onSelect={ onSelectImage }
onSelectURL={ onSelectURL }
onError={ onUploadError }
placeholder={ placeholder }
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
value={ { id, src } }
mediaPreview={ mediaPreview }
disableMediaButtons={ temporaryURL || url }
/>
</figure>
{
// The listener cannot be placed as the first element as it will break the in-between inserter.
// See https://github.com/WordPress/gutenberg/blob/71134165868298fc15e22896d0c28b41b3755ff7/packages/block-editor/src/components/block-list/use-in-between-inserter.js#L120
contentResizeListener
}
</>
);
}

Expand Down
21 changes: 19 additions & 2 deletions packages/block-library/src/image/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export default function Image( {
clientId,
blockEditingMode,
parentLayoutType,
containerWidth,
} ) {
const {
url = '',
Expand Down Expand Up @@ -928,6 +929,7 @@ export default function Image( {
// @todo It would be good to revisit this once a content-width variable
// becomes available.
const maxWidthBuffer = maxWidth * 2.5;
const maxContentWidth = containerWidth || maxWidthBuffer;

let showRightHandle = false;
let showLeftHandle = false;
Expand Down Expand Up @@ -973,9 +975,9 @@ export default function Image( {
} }
showHandle={ isSingleSelected }
minWidth={ minWidth }
maxWidth={ maxWidthBuffer }
maxWidth={ maxContentWidth }
minHeight={ minHeight }
maxHeight={ maxWidthBuffer / ratio }
maxHeight={ maxContentWidth / ratio }
lockAspectRatio={ ratio }
enable={ {
top: false,
Expand All @@ -986,6 +988,21 @@ export default function Image( {
onResizeStart={ onResizeStart }
onResizeStop={ ( event, direction, elt ) => {
onResizeStop();

// Clear hardcoded width if the resized width is close to the max-content width.
if (
// Only do this if the image is bigger than the container to prevent it from being squished.
// TODO: Remove this check if the image support setting 100% width.
naturalWidth >= maxContentWidth &&
Math.abs( elt.offsetWidth - maxContentWidth ) < 10
) {
setAttributes( {
width: undefined,
height: undefined,
} );
return;
}

// Since the aspect ratio is locked when resizing, we can
// use the width of the resized element to calculate the
// height in CSS to prevent stretching when the max-width
Expand Down

0 comments on commit c7c8c4b

Please sign in to comment.