Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limit the max width of image to its container size #63341

Merged
merged 5 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -108,6 +108,7 @@ export default function Image( {
clientId,
blockEditingMode,
parentLayoutType,
containerWidth,
} ) {
const {
url = '',
Expand Down Expand Up @@ -923,6 +924,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 @@ -968,9 +970,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 @@ -981,6 +983,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
Loading