From 95f451c894d00e79e9ab73e8fcc3d0878a9ae6ea Mon Sep 17 00:00:00 2001 From: Sukhendu Sekhar Guria Date: Thu, 16 Jul 2026 11:30:48 +0530 Subject: [PATCH] fix(media): require dimensions for auto-sizes --- src/wp-includes/deprecated.php | 6 ++- src/wp-includes/media.php | 22 +++++++---- tests/phpunit/tests/media.php | 72 ++++++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 13 deletions(-) diff --git a/src/wp-includes/deprecated.php b/src/wp-includes/deprecated.php index 14f5c24aec914..ddfce29bd803a 100644 --- a/src/wp-includes/deprecated.php +++ b/src/wp-includes/deprecated.php @@ -6463,7 +6463,8 @@ function wp_add_editor_classic_theme_styles( $editor_settings ) { * Prints a CSS rule to fix potential visual issues with images using `sizes=auto`. * * This rule overrides the similar rule in the default user agent stylesheet, to avoid images that use e.g. - * `width: auto` or `width: fit-content` to appear smaller. + * `width: auto` or `width: fit-content` to appear smaller. It only applies to images with dimensions, since + * otherwise the enlarged intrinsic height can cause the image to appear stretched. * * @since 6.7.1 * @deprecated 6.9.0 Use wp_enqueue_img_auto_sizes_contain_css_fix() instead. @@ -6471,6 +6472,7 @@ function wp_add_editor_classic_theme_styles( $editor_settings ) { * * @see https://html.spec.whatwg.org/multipage/rendering.html#img-contain-size * @see https://core.trac.wordpress.org/ticket/62413 + * @see https://core.trac.wordpress.org/ticket/62515 * @see https://core.trac.wordpress.org/ticket/62731 */ function wp_print_auto_sizes_contain_css_fix() { @@ -6483,7 +6485,7 @@ function wp_print_auto_sizes_contain_css_fix() { } ?> - + get_attribute( 'width' ); - if ( ! is_string( $width ) || '' === $width ) { + $width = $processor->get_attribute( 'width' ); + $height = $processor->get_attribute( 'height' ); + if ( ! is_string( $width ) || '' === $width || ! is_string( $height ) || '' === $height ) { return $image; } @@ -2185,12 +2189,14 @@ function wp_sizes_attribute_includes_valid_auto( string $sizes_attr ): bool { * Enqueues a CSS rule to fix potential visual issues with images using `sizes=auto`. * * This rule overrides the similar rule in the default user agent stylesheet, to avoid images that use e.g. - * `width: auto` or `width: fit-content` to appear smaller. + * `width: auto` or `width: fit-content` to appear smaller. It only applies to images with dimensions, since + * otherwise the enlarged intrinsic height can cause the image to appear stretched. * * @since 6.9.0 * * @see https://html.spec.whatwg.org/multipage/rendering.html#img-contain-size * @see https://core.trac.wordpress.org/ticket/62413 + * @see https://core.trac.wordpress.org/ticket/62515 * @see https://core.trac.wordpress.org/ticket/62731 */ function wp_enqueue_img_auto_sizes_contain_css_fix(): void { @@ -2209,7 +2215,7 @@ function wp_enqueue_img_auto_sizes_contain_css_fix(): void { $handle = 'wp-img-auto-sizes-contain'; wp_register_style( $handle, false ); - wp_add_inline_style( $handle, 'img:is([sizes=auto i],[sizes^="auto," i]){contain-intrinsic-size:3000px 1500px}' ); + wp_add_inline_style( $handle, 'img:where([width][height]):is([sizes=auto i],[sizes^="auto," i]){contain-intrinsic-size:3000px 1500px}' ); // Make sure inline style is printed first since it was previously printed at wp_head priority 1 and this preserves the CSS cascade. array_unshift( wp_styles()->queue, $handle ); diff --git a/tests/phpunit/tests/media.php b/tests/phpunit/tests/media.php index 03fe3b4c02460..9c6845933e7a4 100644 --- a/tests/phpunit/tests/media.php +++ b/tests/phpunit/tests/media.php @@ -6789,17 +6789,27 @@ public function test_image_without_lazy_loading_does_not_have_auto_sizes() { * * @ticket 61847 * @ticket 62413 + * @ticket 62515 */ public function test_image_without_width_does_not_have_auto_sizes() { // Disable automatic width calculation. add_filter( 'wp_get_attachment_image_src', function ( $img_data ) { - return array( $img_data[0], null, null ); + return array( $img_data[0], null, $img_data[2] ); } ); - $markup = wp_get_attachment_image( self::$large_id, 'large', false, array( 'loading' => false ) ); + $markup = wp_get_attachment_image( + self::$large_id, + 'large', + false, + array( + 'loading' => 'lazy', + 'srcset' => 'https://example.com/foo-1024x768.jpg 1024w', + 'sizes' => '(max-width: 1024px) 100vw, 1024px', + ) + ); $this->assertStringNotContainsString( 'width="', @@ -6814,6 +6824,44 @@ function ( $img_data ) { ); } + /** + * Test generated markup for an image with no height does not get auto-sizes. + * + * @ticket 62515 + */ + public function test_image_without_height_does_not_have_auto_sizes() { + // Disable automatic height calculation. + add_filter( + 'wp_get_attachment_image_src', + function ( $img_data ) { + return array( $img_data[0], $img_data[1], null ); + } + ); + + $markup = wp_get_attachment_image( + self::$large_id, + 'large', + false, + array( + 'loading' => 'lazy', + 'srcset' => 'https://example.com/foo-1024x768.jpg 1024w', + 'sizes' => '(max-width: 1024px) 100vw, 1024px', + ) + ); + + $this->assertStringNotContainsString( + 'height="', + $markup, + 'Failed confirming the test markup did not include a height attribute.' + ); + + $this->assertStringNotContainsString( + 'sizes="auto, ', + $markup, + 'Failed asserting that the sizes attribute for an image without a height does not include "auto".' + ); + } + /** * Test content filtered markup with lazy loading gets auto-sizes. * @@ -7094,6 +7142,7 @@ static function () { * * @covers ::wp_enqueue_img_auto_sizes_contain_css_fix * @ticket 62731 + * @ticket 62515 * * @dataProvider data_provider_data_provider_to_test_wp_enqueue_img_auto_sizes_contain_css_fix */ @@ -7118,7 +7167,14 @@ static function () { } ); - $wp_head_output = get_echo( 'wp_head' ); + $wp_head_output = get_echo( 'wp_head' ); + if ( isset( $expected_deprecated ) ) { + $this->assertStringContainsString( + 'img:where([width][height]):is([sizes="auto" i], [sizes^="auto," i])', + $wp_head_output, + 'Failed asserting that the deprecated CSS output includes the dimension guard.' + ); + } $html_processor = new WP_HTML_Tag_Processor( $wp_head_output ); $found_style_text_content = null; while ( $html_processor->next_tag( array( 'tag_name' => 'STYLE' ) ) ) { @@ -7133,6 +7189,7 @@ static function () { $this->assertSame( 'wp-img-auto-sizes-contain', array_shift( $enqueued ) ); $this->assertIsString( $found_style_text_content ); $this->assertStringContainsString( 'contain-intrinsic-size', $found_style_text_content ); + $this->assertStringContainsString( 'img:where([width][height])', $found_style_text_content ); } else { $this->assertNull( $found_style_text_content ); } @@ -7192,11 +7249,20 @@ public function data_provider_to_test_wp_img_tag_add_auto_sizes() { 'input' => '', 'expected' => '', ), + 'not_expected_when_img_lacks_height' => array( + 'input' => '', + 'expected' => '', + ), + 'not_expected_when_img_lacks_width' => array( + 'input' => '', + 'expected' => '', + ), ); } /** * @ticket 61847 + * @ticket 62515 * * @covers ::wp_img_tag_add_auto_sizes *