Commit a7dda35133 for wordpress.org

commit a7dda351333fd4639a920774cac1260277e2ea38
Author: Felix Arntz <felix-arntz@leaves-and-love.net>
Date:   Mon Nov 18 19:52:19 2024 +0000

    Media: Avoid images with `sizes=auto` to be displayed downsized in supporting browsers.

    Based on the user agent stylesheet rules outlined in https://html.spec.whatwg.org/multipage/rendering.html#img-contain-size, images that have `sizes=auto` while applying `width: auto` or `width: fit-content` would be constrained to only 300px width.

    This changeset overrides said user agent stylesheet rule with a much larger constraint, to avoid the problem.

    Additionally, it introduces a filter `wp_img_tag_add_auto_sizes` which can be used to opt out of the functionality, as an additional measure.

    Props joemcgill, flixos90, dooperweb, SirLouen, azaozz, mukesh27, apermo.
    Fixes #62413.
    See #61847, #62345.

    Built from https://develop.svn.wordpress.org/trunk@59415


    git-svn-id: http://core.svn.wordpress.org/trunk@58801 1a063a9b-81f0-0310-95a4-ce76da25c4cd

diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php
index 961b37f9aa..ae654605e8 100644
--- a/wp-includes/default-filters.php
+++ b/wp-includes/default-filters.php
@@ -611,6 +611,7 @@ add_action( 'wp_footer', 'wp_enqueue_stored_styles', 1 );
 add_action( 'wp_default_styles', 'wp_default_styles' );
 add_filter( 'style_loader_src', 'wp_style_loader_src', 10, 2 );

+add_action( 'wp_head', 'wp_print_auto_sizes_contain_css_fix', 1 );
 add_action( 'wp_head', 'wp_maybe_inline_styles', 1 ); // Run for styles enqueued in <head>.
 add_action( 'wp_footer', 'wp_maybe_inline_styles', 1 ); // Run for late-loaded styles in the footer.

diff --git a/wp-includes/media.php b/wp-includes/media.php
index 6e58658189..00e23ff53d 100644
--- a/wp-includes/media.php
+++ b/wp-includes/media.php
@@ -1137,8 +1137,12 @@ function wp_get_attachment_image( $attachment_id, $size = 'thumbnail', $icon = f
 			}
 		}

+		/** This filter is documented in wp-includes/media.php */
+		$add_auto_sizes = apply_filters( 'wp_img_tag_add_auto_sizes', true );
+
 		// Adds 'auto' to the sizes attribute if applicable.
 		if (
+			$add_auto_sizes &&
 			isset( $attr['loading'] ) &&
 			'lazy' === $attr['loading'] &&
 			isset( $attr['sizes'] ) &&
@@ -1985,6 +1989,17 @@ function wp_filter_content_tags( $content, $context = null ) {
  * @return string The filtered image tag markup.
  */
 function wp_img_tag_add_auto_sizes( string $image ): string {
+	/**
+	 * Filters whether auto-sizes for lazy loaded images is enabled.
+	 *
+	 * @since 6.7.1
+	 *
+	 * @param boolean $enabled Whether auto-sizes for lazy loaded images is enabled.
+	 */
+	if ( ! apply_filters( 'wp_img_tag_add_auto_sizes', true ) ) {
+		return $image;
+	}
+
 	$processor = new WP_HTML_Tag_Processor( $image );

 	// Bail if there is no IMG tag.
@@ -1993,8 +2008,19 @@ function wp_img_tag_add_auto_sizes( string $image ): string {
 	}

 	// Bail early if the image is not lazy-loaded.
-	$value = $processor->get_attribute( 'loading' );
-	if ( ! is_string( $value ) || 'lazy' !== strtolower( trim( $value, " \t\f\r\n" ) ) ) {
+	$loading = $processor->get_attribute( 'loading' );
+	if ( ! is_string( $loading ) || 'lazy' !== strtolower( trim( $loading, " \t\f\r\n" ) ) ) {
+		return $image;
+	}
+
+	/*
+	 * Bail early if the image doesn't have a width attribute.
+	 * Per WordPress Core itself, lazy-loaded images should always have a width attribute.
+	 * 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`.
+	 */
+	$width = $processor->get_attribute( 'width' );
+	if ( ! is_string( $width ) || '' === $width ) {
 		return $image;
 	}

@@ -2029,6 +2055,28 @@ function wp_sizes_attribute_includes_valid_auto( string $sizes_attr ): bool {
 	return 'auto' === strtolower( trim( $first_size, " \t\f\r\n" ) );
 }

+/**
+ * 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.
+ *
+ * @since 6.7.1
+ * @see https://html.spec.whatwg.org/multipage/rendering.html#img-contain-size
+ * @see https://core.trac.wordpress.org/ticket/62413
+ */
+function wp_print_auto_sizes_contain_css_fix() {
+	/** This filter is documented in wp-includes/media.php */
+	$add_auto_sizes = apply_filters( 'wp_img_tag_add_auto_sizes', true );
+	if ( ! $add_auto_sizes ) {
+		return;
+	}
+
+	?>
+	<style>img:is([sizes="auto" i], [sizes^="auto," i]) { contain-intrinsic-size: 3000px 1500px }</style>
+	<?php
+}
+
 /**
  * Adds optimization attributes to an `img` HTML tag.
  *
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 44ef220047..7d424870bb 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '6.8-alpha-59414';
+$wp_version = '6.8-alpha-59415';

 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.