Make WordPress Core


Ignore:
Timestamp:
09/10/2024 11:59:54 PM (4 months ago)
Author:
joemcgill
Message:

Media: Add auto sizes for lazy-loaded images.

This implements the HTML spec for applying auto sizes to lazy-loaded images by prepending auto to the sizes attribute generated by WordPress if the image has a loading attribute set to lazy. For browser that support this HTML spec, the image's size value will be set to the concrete object size of the image. For browsers that don't support the spec, the word "auto" will be ignored when parsing the sizes value.

References:

Props mukesh27, flixos90, joemcgill, westonruter, peterwilsoncc.
Fixes #61847.

File:
1 edited

Legend:

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

    r58974 r59008  
    11381138        }
    11391139
     1140        // Adds 'auto' to the sizes attribute if applicable.
     1141        if (
     1142            isset( $attr['loading'] ) &&
     1143            'lazy' === $attr['loading'] &&
     1144            isset( $attr['sizes'] ) &&
     1145            ! wp_sizes_attribute_includes_valid_auto( $attr['sizes'] )
     1146        ) {
     1147            $attr['sizes'] = 'auto, ' . $attr['sizes'];
     1148        }
     1149
    11401150        /**
    11411151         * Filters the list of attachment image attributes.
     
    19181928            $filtered_image = wp_img_tag_add_loading_optimization_attrs( $filtered_image, $context );
    19191929
     1930            // Adds 'auto' to the sizes attribute if applicable.
     1931            $filtered_image = wp_img_tag_add_auto_sizes( $filtered_image );
     1932
    19201933            /**
    19211934             * Filters an img tag within the content for a given context.
     
    19621975
    19631976    return $content;
     1977}
     1978
     1979/**
     1980 * Adds 'auto' to the sizes attribute to the image, if the image is lazy loaded and does not already include it.
     1981 *
     1982 * @since 6.7.0
     1983 *
     1984 * @param string $image The image tag markup being filtered.
     1985 * @return string The filtered image tag markup.
     1986 */
     1987function wp_img_tag_add_auto_sizes( string $image ): string {
     1988    $processor = new WP_HTML_Tag_Processor( $image );
     1989
     1990    // Bail if there is no IMG tag.
     1991    if ( ! $processor->next_tag( array( 'tag_name' => 'IMG' ) ) ) {
     1992        return $image;
     1993    }
     1994
     1995    // Bail early if the image is not lazy-loaded.
     1996    $value = $processor->get_attribute( 'loading' );
     1997    if ( ! is_string( $value ) || 'lazy' !== strtolower( trim( $value, " \t\f\r\n" ) ) ) {
     1998        return $image;
     1999    }
     2000
     2001    $sizes = $processor->get_attribute( 'sizes' );
     2002
     2003    // Bail early if the image is not responsive.
     2004    if ( ! is_string( $sizes ) ) {
     2005        return $image;
     2006    }
     2007
     2008    // Don't add 'auto' to the sizes attribute if it already exists.
     2009    if ( wp_sizes_attribute_includes_valid_auto( $sizes ) ) {
     2010        return $image;
     2011    }
     2012
     2013    $processor->set_attribute( 'sizes', "auto, $sizes" );
     2014    return $processor->get_updated_html();
     2015}
     2016
     2017/**
     2018 * Checks whether the given 'sizes' attribute includes the 'auto' keyword as the first item in the list.
     2019 *
     2020 * Per the HTML spec, if present it must be the first entry.
     2021 *
     2022 * @since 6.7.0
     2023 *
     2024 * @param string $sizes_attr The 'sizes' attribute value.
     2025 * @return bool True if the 'auto' keyword is present, false otherwise.
     2026 */
     2027function wp_sizes_attribute_includes_valid_auto( string $sizes_attr ): bool {
     2028    list( $first_size ) = explode( ',', $sizes_attr, 2 );
     2029    return 'auto' === strtolower( trim( $first_size, " \t\f\r\n" ) );
    19642030}
    19652031
Note: See TracChangeset for help on using the changeset viewer.