Make WordPress Core


Ignore:
Timestamp:
05/22/2023 07:11:36 PM (6 months ago)
Author:
flixos90
Message:

Media: Conditionally skip lazy-loading on images before the loop to improve LCP performance.

When the logic to exclude images that likely appear above the fold from being lazy-loaded was introduced in WordPress 5.9, initially only images that appear within the main query loop were being considered. However, there is a good chance that images above the fold are rendered before the loop starts, for example in the header template part.

It is particularly common for a theme to display the featured image for a single post in the header. Based on HTTP Archive data from February 2023, the majority of LCP images that are still being lazy-loaded on WordPress sites use the wp-post-image class, i.e. are featured images.

This changeset enhances the logic in wp_get_loading_attr_default() to not lazy-load images that appear within or after the header template part and before the query loop, using a new WP_Query::$before_loop property.

For block themes, this was for the most part already addressed in [55318], however this enhancement implements the solution in a more generally applicable way that brings the improvement to classic themes as well.

Props thekt12, flixos90, spacedmonkey, costdev, zunaid321, mukesh27.
Fixes #58211.
See #53675, #56930.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/media.php

    r55843 r55847  
    54915491 * @since 5.9.0
    54925492 *
     5493 * @global WP_Query $wp_query WordPress Query object.
     5494 *
    54935495 * @param string $context Context for the element for which the `loading` attribute value is requested.
    54945496 * @return string|bool The default `loading` attribute value. Either 'lazy', 'eager', or a boolean `false`, to indicate
     
    54965498 */
    54975499function wp_get_loading_attr_default( $context ) {
     5500    global $wp_query;
     5501
    54985502    // Skip lazy-loading for the overall block template, as it is handled more granularly.
    54995503    if ( 'template' === $context ) {
     
    55025506
    55035507    // Do not lazy-load images in the header block template part, as they are likely above the fold.
     5508    // For classic themes, this is handled in the condition below using the 'get_header' action.
    55045509    $header_area = WP_TEMPLATE_PART_AREA_HEADER;
    55055510    if ( "template_part_{$header_area}" === $context ) {
     
    55075512    }
    55085513
    5509     /*
    5510      * Skip programmatically created images within post content as they need to be handled together with the other
    5511      * images within the post content.
    5512      * Without this clause, they would already be counted below which skews the number and can result in the first
    5513      * post content image being lazy-loaded only because there are images elsewhere in the post content.
    5514      */
    5515     if ( ( 'the_post_thumbnail' === $context || 'wp_get_attachment_image' === $context ) && doing_filter( 'the_content' ) ) {
    5516         return false;
     5514    // Special handling for programmatically created image tags.
     5515    if ( ( 'the_post_thumbnail' === $context || 'wp_get_attachment_image' === $context ) ) {
     5516        /*
     5517         * Skip programmatically created images within post content as they need to be handled together with the other
     5518         * images within the post content.
     5519         * Without this clause, they would already be counted below which skews the number and can result in the first
     5520         * post content image being lazy-loaded only because there are images elsewhere in the post content.
     5521         */
     5522        if ( doing_filter( 'the_content' ) ) {
     5523            return false;
     5524        }
     5525
     5526        // Conditionally skip lazy-loading on images before the loop.
     5527        if (
     5528            // Only apply for main query but before the loop.
     5529            $wp_query->before_loop && $wp_query->is_main_query()
     5530            /*
     5531             * Any image before the loop, but after the header has started should not be lazy-loaded,
     5532             * except when the footer has already started which can happen when the current template
     5533             * does not include any loop.
     5534             */
     5535            && did_action( 'get_header' ) && ! did_action( 'get_footer' )
     5536        ) {
     5537            return false;
     5538        }
    55175539    }
    55185540
Note: See TracChangeset for help on using the changeset viewer.