Skip to content
Open
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
6 changes: 4 additions & 2 deletions src/wp-includes/deprecated.php
Original file line number Diff line number Diff line change
Expand Up @@ -6463,14 +6463,16 @@ 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.
* @see wp_enqueue_img_auto_sizes_contain_css_fix()
*
* @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() {
Expand All @@ -6483,7 +6485,7 @@ function wp_print_auto_sizes_contain_css_fix() {
}

?>
<style>img:is([sizes="auto" i], [sizes^="auto," i]) { contain-intrinsic-size: 3000px 1500px }</style>
<style>img:where([width][height]):is([sizes="auto" i], [sizes^="auto," i]) { contain-intrinsic-size: 3000px 1500px }</style>
<?php
}

Expand Down
22 changes: 14 additions & 8 deletions src/wp-includes/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,8 @@ function wp_get_attachment_image( $attachment_id, $size = 'thumbnail', $icon = f
// Adds 'auto' to the sizes attribute if applicable.
if (
$add_auto_sizes &&
! empty( $attr['width'] ) &&
! empty( $attr['height'] ) &&
isset( $attr['loading'] ) &&
'lazy' === $attr['loading'] &&
isset( $attr['sizes'] ) &&
Expand Down Expand Up @@ -2107,7 +2109,8 @@ function wp_filter_content_tags( $content, $context = null ) {
}

/**
* Adds 'auto' to the sizes attribute to the image, if the image is lazy loaded and does not already include it.
* Adds 'auto' to the sizes attribute if the image is lazy loaded, has width and height attributes,
* and does not already include it.
*
* @since 6.7.0
*
Expand Down Expand Up @@ -2140,13 +2143,14 @@ function wp_img_tag_add_auto_sizes( string $image ): string {
}

/*
* Bail early if the image doesn't have a width attribute.
* Per WordPress Core itself, lazy-loaded images should always have a width attribute.
* Bail early if the image doesn't have width and height attributes.
* Per WordPress Core itself, lazy-loaded images should always have width and height attributes.
* However, it is possible that lazy-loading could be added by a plugin, where we don't have that guarantee.
* As such, it still makes sense to ensure presence of a width attribute here in order to use `sizes=auto`.
* As such, it still makes sense to ensure presence of both attributes here in order to use `sizes=auto`.
*/
$width = $processor->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;
}

Expand Down Expand Up @@ -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 {
Expand All @@ -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 );
Expand Down
72 changes: 69 additions & 3 deletions tests/phpunit/tests/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -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="',
Expand All @@ -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.
*
Expand Down Expand Up @@ -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
*/
Expand All @@ -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' ) ) ) {
Expand All @@ -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 );
}
Expand Down Expand Up @@ -7192,11 +7249,20 @@ public function data_provider_to_test_wp_img_tag_add_auto_sizes() {
'input' => '<img data-tshirt-sizes="S M L" src="https://example.com/foo-300x225.jpg" srcset="https://example.com/foo-300x225.jpg 300w, https://example.com/foo-1024x768.jpg 1024w, https://example.com/foo-768x576.jpg 768w, https://example.com/foo-1536x1152.jpg 1536w, https://example.com/foo-2048x1536.jpg 2048w" sizes="(max-width: 650px) 100vw, 650px" loading="lazy">',
'expected' => '<img data-tshirt-sizes="S M L" src="https://example.com/foo-300x225.jpg" srcset="https://example.com/foo-300x225.jpg 300w, https://example.com/foo-1024x768.jpg 1024w, https://example.com/foo-768x576.jpg 768w, https://example.com/foo-1536x1152.jpg 1536w, https://example.com/foo-2048x1536.jpg 2048w" sizes="(max-width: 650px) 100vw, 650px" loading="lazy">',
),
'not_expected_when_img_lacks_height' => array(
'input' => '<img width="300" src="https://example.com/foo-300x225.jpg" srcset="https://example.com/foo-300x225.jpg 300w, https://example.com/foo-1024x768.jpg 1024w" sizes="(max-width: 650px) 100vw, 650px" loading="lazy">',
'expected' => '<img width="300" src="https://example.com/foo-300x225.jpg" srcset="https://example.com/foo-300x225.jpg 300w, https://example.com/foo-1024x768.jpg 1024w" sizes="(max-width: 650px) 100vw, 650px" loading="lazy">',
),
'not_expected_when_img_lacks_width' => array(
'input' => '<img height="225" src="https://example.com/foo-300x225.jpg" srcset="https://example.com/foo-300x225.jpg 300w, https://example.com/foo-1024x768.jpg 1024w" sizes="(max-width: 650px) 100vw, 650px" loading="lazy">',
'expected' => '<img height="225" src="https://example.com/foo-300x225.jpg" srcset="https://example.com/foo-300x225.jpg 300w, https://example.com/foo-1024x768.jpg 1024w" sizes="(max-width: 650px) 100vw, 650px" loading="lazy">',
),
);
}

/**
* @ticket 61847
* @ticket 62515
*
* @covers ::wp_img_tag_add_auto_sizes
*
Expand Down
Loading