@@ -5967,6 +5967,7 @@ function wp_get_webp_info( $filename ) {
59675967 * both attributes are present with those values.
59685968 *
59695969 * @since 6.3.0
5970+ * @since 7.0.0 Support `fetchpriority=low` and `fetchpriority=auto` so that `loading=lazy` is not added and the media count is not increased.
59705971 *
59715972 * @global WP_Query $wp_query WordPress Query object.
59725973 *
@@ -6067,7 +6068,9 @@ function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) {
60676068 }
60686069
60696070 // Logic to handle a `fetchpriority` attribute that is already provided.
6070- if ( isset ( $ attr ['fetchpriority ' ] ) && 'high ' === $ attr ['fetchpriority ' ] ) {
6071+ $ existing_fetchpriority = ( $ attr ['fetchpriority ' ] ?? null );
6072+ $ is_low_fetchpriority = ( 'low ' === $ existing_fetchpriority );
6073+ if ( 'high ' === $ existing_fetchpriority ) {
60716074 /*
60726075 * If the image was already determined to not be in the viewport (e.g.
60736076 * from an already provided `loading` attribute), trigger a warning.
@@ -6090,6 +6093,31 @@ function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) {
60906093 } else {
60916094 $ maybe_in_viewport = true ;
60926095 }
6096+ } elseif ( $ is_low_fetchpriority ) {
6097+ /*
6098+ * An IMG with fetchpriority=low is not initially displayed; it may be hidden in the Navigation Overlay,
6099+ * or it may be occluded in a non-initial carousel slide. Such images must not be lazy-loaded because the browser
6100+ * has no heuristic to know when to start loading them before the user needs to see them.
6101+ */
6102+ $ maybe_in_viewport = false ;
6103+
6104+ // Preserve fetchpriority=low.
6105+ $ loading_attrs ['fetchpriority ' ] = 'low ' ;
6106+ } elseif ( 'auto ' === $ existing_fetchpriority ) {
6107+ /*
6108+ * When a block's visibility support identifies that the block is conditionally displayed based on the viewport
6109+ * size, then it adds `fetchpriority=auto` to the block's IMG tags. These images must not be fetched with high
6110+ * priority because they could be erroneously loaded in viewports which do not even display them. Contrarily,
6111+ * they must not get `fetchpriority=low` because they may in fact be displayed in the current viewport. So as
6112+ * a signal to indicate that an IMG may be in the viewport, `fetchpriority=auto` is added. This has the effect
6113+ * here of preventing the media count from being increased, so that images hidden with block visibility do not
6114+ * affect whether a following IMG gets `loading=lazy`. In particular, `loading=lazy` should still be omitted
6115+ * on an IMG following any number of initial IMGs with `fetchpriority=auto` since those initial images may not
6116+ * be displayed.
6117+ */
6118+
6119+ // Preserve fetchpriority=auto.
6120+ $ loading_attrs ['fetchpriority ' ] = 'auto ' ;
60936121 }
60946122
60956123 if ( null === $ maybe_in_viewport ) {
@@ -6140,7 +6168,7 @@ function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) {
61406168 * does not include any loop.
61416169 */
61426170 && did_action ( 'get_header ' ) && ! did_action ( 'get_footer ' )
6143- ) {
6171+ ) {
61446172 $ maybe_in_viewport = true ;
61456173 $ maybe_increase_count = true ;
61466174 }
@@ -6149,12 +6177,14 @@ function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) {
61496177 /*
61506178 * If the element is in the viewport (`true`), potentially add
61516179 * `fetchpriority` with a value of "high". Otherwise, i.e. if the element
6152- * is not not in the viewport (`false`) or it is unknown (`null`), add
6153- * `loading` with a value of "lazy".
6180+ * is not in the viewport (`false`) or it is unknown (`null`), add
6181+ * `loading` with a value of "lazy" if the element is not already being
6182+ * de-prioritized with `fetchpriority=low` due to occlusion in
6183+ * Navigation Overlay, non-initial carousel slides, or a collapsed Details block.
61546184 */
61556185 if ( $ maybe_in_viewport ) {
61566186 $ loading_attrs = wp_maybe_add_fetchpriority_high_attr ( $ loading_attrs , $ tag_name , $ attr );
6157- } else {
6187+ } elseif ( ! $ is_low_fetchpriority ) {
61586188 // Only add `loading="lazy"` if the feature is enabled.
61596189 if ( wp_lazy_loading_enabled ( $ tag_name , $ context ) ) {
61606190 $ loading_attrs ['loading ' ] = 'lazy ' ;
@@ -6164,16 +6194,20 @@ function wp_get_loading_optimization_attributes( $tag_name, $attr, $context ) {
61646194 /*
61656195 * If flag was set based on contextual logic above, increase the content
61666196 * media count, either unconditionally, or based on whether the image size
6167- * is larger than the threshold.
6197+ * is larger than the threshold. This does not apply when the IMG has
6198+ * fetchpriority=auto because it may be conditionally displayed by viewport
6199+ * size.
61686200 */
6169- if ( $ increase_count ) {
6170- wp_increase_content_media_count ();
6171- } elseif ( $ maybe_increase_count ) {
6172- /** This filter is documented in wp-includes/media.php */
6173- $ wp_min_priority_img_pixels = apply_filters ( 'wp_min_priority_img_pixels ' , 50000 );
6174-
6175- if ( $ wp_min_priority_img_pixels <= $ attr ['width ' ] * $ attr ['height ' ] ) {
6201+ if ( 'auto ' !== $ existing_fetchpriority ) {
6202+ if ( $ increase_count ) {
61766203 wp_increase_content_media_count ();
6204+ } elseif ( $ maybe_increase_count ) {
6205+ /** This filter is documented in wp-includes/media.php */
6206+ $ wp_min_priority_img_pixels = apply_filters ( 'wp_min_priority_img_pixels ' , 50000 );
6207+
6208+ if ( $ wp_min_priority_img_pixels <= $ attr ['width ' ] * $ attr ['height ' ] ) {
6209+ wp_increase_content_media_count ();
6210+ }
61776211 }
61786212 }
61796213
@@ -6245,27 +6279,31 @@ function wp_increase_content_media_count( $amount = 1 ) {
62456279 * Determines whether to add `fetchpriority='high'` to loading attributes.
62466280 *
62476281 * @since 6.3.0
6282+ * @since 7.0.0 Support is added for IMG tags with `fetchpriority='low'` and `fetchpriority='auto'`.
62486283 * @access private
62496284 *
6250- * @param array $loading_attrs Array of the loading optimization attributes for the element.
6251- * @param string $tag_name The tag name.
6252- * @param array $attr Array of the attributes for the element.
6253- * @return array Updated loading optimization attributes for the element.
6285+ * @param array<string, string> $loading_attrs Array of the loading optimization attributes for the element.
6286+ * @param string $tag_name The tag name.
6287+ * @param array<string, mixed> $attr Array of the attributes for the element.
6288+ * @return array<string, string> Updated loading optimization attributes for the element.
62546289 */
62556290function wp_maybe_add_fetchpriority_high_attr ( $ loading_attrs , $ tag_name , $ attr ) {
62566291 // For now, adding `fetchpriority="high"` is only supported for images.
62576292 if ( 'img ' !== $ tag_name ) {
62586293 return $ loading_attrs ;
62596294 }
62606295
6261- if ( isset ( $ attr ['fetchpriority ' ] ) ) {
6296+ $ existing_fetchpriority = $ attr ['fetchpriority ' ] ?? null ;
6297+ if ( null !== $ existing_fetchpriority && 'auto ' !== $ existing_fetchpriority ) {
62626298 /*
6263- * While any `fetchpriority` value could be set in `$loading_attrs`,
6264- * for consistency we only do it for `fetchpriority="high"` since that
6265- * is the only possible value that WordPress core would apply on its
6266- * own.
6299+ * When an IMG has been explicitly marked with `fetchpriority=high`, then honor that this is the element that
6300+ * should have the priority. In contrast, the Navigation block may add `fetchpriority=low` to an IMG which
6301+ * appears in the Navigation Overlay; such images should never be considered candidates for
6302+ * `fetchpriority=high`. Lastly, block visibility may add `fetchpriority=auto` to an IMG when the block is
6303+ * conditionally displayed based on viewport size. Such an image is considered an LCP element candidate if it
6304+ * exceeds the threshold for the minimum number of square pixels.
62676305 */
6268- if ( 'high ' === $ attr [ ' fetchpriority ' ] ) {
6306+ if ( 'high ' === $ existing_fetchpriority ) {
62696307 $ loading_attrs ['fetchpriority ' ] = 'high ' ;
62706308 wp_high_priority_element_flag ( false );
62716309 }
@@ -6292,7 +6330,9 @@ function wp_maybe_add_fetchpriority_high_attr( $loading_attrs, $tag_name, $attr
62926330 $ wp_min_priority_img_pixels = apply_filters ( 'wp_min_priority_img_pixels ' , 50000 );
62936331
62946332 if ( $ wp_min_priority_img_pixels <= $ attr ['width ' ] * $ attr ['height ' ] ) {
6295- $ loading_attrs ['fetchpriority ' ] = 'high ' ;
6333+ if ( 'auto ' !== $ existing_fetchpriority ) {
6334+ $ loading_attrs ['fetchpriority ' ] = 'high ' ;
6335+ }
62966336 wp_high_priority_element_flag ( false );
62976337 }
62986338
@@ -6306,9 +6346,9 @@ function wp_maybe_add_fetchpriority_high_attr( $loading_attrs, $tag_name, $attr
63066346 * @access private
63076347 *
63086348 * @param bool $value Optional. Used to change the static variable. Default null.
6309- * @return bool Returns true if high-priority element was marked already, otherwise false .
6349+ * @return bool Returns true if the high-priority element was not already marked .
63106350 */
6311- function wp_high_priority_element_flag ( $ value = null ) {
6351+ function wp_high_priority_element_flag ( $ value = null ): bool {
63126352 static $ high_priority_element = true ;
63136353
63146354 if ( is_bool ( $ value ) ) {
0 commit comments