Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compute responsive sizes attribute based on the width from the boundingClientRect in captured URL Metrics #1840

Merged
merged 13 commits into from
Feb 8, 2025

Conversation

westonruter
Copy link
Member

@westonruter westonruter commented Feb 3, 2025

Summary

Given a post that contains a columns block with three images in it, which are displayed without columns on a non-desktop viewport:

Desktop Mobile
image image
Block markup
<!-- wp:columns -->
<div class="wp-block-columns"><!-- wp:column {"width":"25%"} -->
<div class="wp-block-column" style="flex-basis:25%"><!-- wp:image {"id":12,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="http://localhost:8888/wp-content/uploads/2024/06/bison2-1024x673.jpg" alt="" class="wp-image-12"/></figure>
<!-- /wp:image --></div>
<!-- /wp:column -->

<!-- wp:column {"width":"50%"} -->
<div class="wp-block-column" style="flex-basis:50%"><!-- wp:image {"id":13,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="http://localhost:8888/wp-content/uploads/2024/06/bison1-1024x668.jpg" alt="" class="wp-image-13"/></figure>
<!-- /wp:image --></div>
<!-- /wp:column -->

<!-- wp:column {"width":"25%"} -->
<div class="wp-block-column" style="flex-basis:25%"><!-- wp:image {"id":11,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="http://localhost:8888/wp-content/uploads/2024/06/bison3-1024x683.jpg" alt="" class="wp-image-11"/></figure>
<!-- /wp:image --></div>
<!-- /wp:column --></div>
<!-- /wp:columns -->

By default, much larger versions of these images are downloaded on desktop than are necessary. For example, even though the first image on desktop only has a rendered size of 136x90, the selected image is much larger at 1536x1010. Nevertheless, the srcset has a much smaller 300x197 pixel image available which would be suitable for rendering instead. The selected image here is 458 KB but the appropriately-sized image is much less at just 22 KB. This represents a significant amount of wasted bytes. This is a difficult problem to solve (as seen in #760) since WordPress does not have layout information readily available to know how large the image will actually be when the page is served across various device form factors. Nevertheless, this information is available on sites using Optimization Detective.

When visitors load a page, the Optimization Detective plugin's detection logic can capture the dimensions of the IMG elements on the page (specifically the boundingClientRect via Intersection Observer). This includes the width of the IMG element on the rendered page for the user's device. This information is then stored in URL Metrics which are put into groups for mobile, phablet, tablet, and desktop. With this URL Metric information stored, when a page is loaded the plugin's optimization logic can use that information to apply relevant performance changes, such as to calculate the sizes based on the collected URL Metrics. This PR explores implementing this as part of the Image Prioritizer extension for Optimization Detective.

Note that Optimization Detective was similarly used to pick a more appropriate image size for a video's poster in #1595 for #1575.

This renders sizes in pixel values, so it may not be as precise/dynamic as what is being explored in #1511.

The following results are specifically looking at desktop. There is no reduction in bytes on mobile because WordPress displays these images as full width on a mobile viewport, and WordPress's default sizes attribute already selects the correct size in that case.

Results

Hovering over the IMG elements in DevTools:

Before After
image image
image image
image image

Images downloaded in Network panel show a ~90% reduction in downloaded bytes:

Before:

image

After:

image

Rendered Markup

Note the change to the sizes attribute.

Before

(This is with Optimization Detective and Image Prioritizer completely disabled by adding ?optimization_detective_disabled to the URL.)

<div
  class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-1 wp-block-columns-is-layout-flex"
>
  <div
    class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"
    style="flex-basis: 25%"
  >
    <figure class="wp-block-image size-large">
      <img
        data-dominant-color="7c7062"
        data-has-transparency="false"
        style="--dominant-color: #7c7062"
        fetchpriority="high"
        decoding="async"
        width="1024"
        height="673"
        sizes="(max-width: 645px) 100vw, 645px"
        src="http://localhost:8888/wp-content/uploads/2024/06/bison2-1024x673.jpg"
        alt=""
        class="wp-image-12 not-transparent"
        srcset="
          http://localhost:8888/wp-content/uploads/2024/06/bison2-1024x673.jpg  1024w,
          http://localhost:8888/wp-content/uploads/2024/06/bison2-300x197.jpg    300w,
          http://localhost:8888/wp-content/uploads/2024/06/bison2-768x505.jpg    768w,
          http://localhost:8888/wp-content/uploads/2024/06/bison2-1536x1010.jpg 1536w,
          http://localhost:8888/wp-content/uploads/2024/06/bison2-2048x1347.jpg 2048w,
          http://localhost:8888/wp-content/uploads/2024/06/bison2-1568x1031.jpg 1568w
        "
      />
    </figure>
  </div>

  <div
    class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"
    style="flex-basis: 50%"
  >
    <figure class="wp-block-image size-large">
      <img
        data-dominant-color="8c7d58"
        data-has-transparency="false"
        style="--dominant-color: #8c7d58"
        decoding="async"
        width="1024"
        height="668"
        sizes="(max-width: 645px) 100vw, 645px"
        src="http://localhost:8888/wp-content/uploads/2024/06/bison1-1024x668.jpg"
        alt=""
        class="wp-image-13 not-transparent"
        srcset="
          http://localhost:8888/wp-content/uploads/2024/06/bison1-1024x668.jpg  1024w,
          http://localhost:8888/wp-content/uploads/2024/06/bison1-300x196.jpg    300w,
          http://localhost:8888/wp-content/uploads/2024/06/bison1-768x501.jpg    768w,
          http://localhost:8888/wp-content/uploads/2024/06/bison1-1536x1002.jpg 1536w,
          http://localhost:8888/wp-content/uploads/2024/06/bison1-2048x1336.jpg 2048w,
          http://localhost:8888/wp-content/uploads/2024/06/bison1-1568x1023.jpg 1568w
        "
      />
    </figure>
  </div>

  <div
    class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"
    style="flex-basis: 25%"
  >
    <figure class="wp-block-image size-large">
      <img
        data-dominant-color="7a6f31"
        data-has-transparency="false"
        style="--dominant-color: #7a6f31"
        decoding="async"
        width="1024"
        height="683"
        sizes="(max-width: 645px) 100vw, 645px"
        src="http://localhost:8888/wp-content/uploads/2024/06/bison3-1024x683.jpg"
        alt=""
        class="wp-image-11 not-transparent"
        srcset="
          http://localhost:8888/wp-content/uploads/2024/06/bison3-1024x683.jpg  1024w,
          http://localhost:8888/wp-content/uploads/2024/06/bison3-300x200.jpg    300w,
          http://localhost:8888/wp-content/uploads/2024/06/bison3-768x513.jpg    768w,
          http://localhost:8888/wp-content/uploads/2024/06/bison3-1536x1025.jpg 1536w,
          http://localhost:8888/wp-content/uploads/2024/06/bison3-2048x1367.jpg 2048w,
          http://localhost:8888/wp-content/uploads/2024/06/bison3-1568x1046.jpg 1568w
        "
      />
    </figure>
  </div>
</div>

After

<div
  class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-1 wp-block-columns-is-layout-flex"
>
  <div
    class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"
    style="flex-basis: 25%"
  >
    <figure class="wp-block-image size-large">
      <img
        data-od-removed-fetchpriority="high"
        data-od-replaced-sizes="(max-width: 1024px) 100vw, 1024px"
        data-dominant-color="7c7062"
        data-has-transparency="false"
        style="--dominant-color: #7c7062"
        decoding="async"
        width="1024"
        height="673"
        sizes="(width &lt;= 480px) 418px, (480px &lt; width &lt;= 600px) 400px, (600px &lt; width &lt;= 782px) 609px, (782px &lt; width) 132px, (max-width: 1024px) 100vw, 1024px"
        src="http://localhost:8888/wp-content/uploads/2024/06/bison2-1024x673.jpg"
        alt=""
        class="wp-image-12 not-transparent"
        srcset="
          http://localhost:8888/wp-content/uploads/2024/06/bison2-1024x673.jpg  1024w,
          http://localhost:8888/wp-content/uploads/2024/06/bison2-300x197.jpg    300w,
          http://localhost:8888/wp-content/uploads/2024/06/bison2-768x505.jpg    768w,
          http://localhost:8888/wp-content/uploads/2024/06/bison2-1536x1010.jpg 1536w,
          http://localhost:8888/wp-content/uploads/2024/06/bison2-2048x1347.jpg 2048w,
          http://localhost:8888/wp-content/uploads/2024/06/bison2-1568x1031.jpg 1568w
        "
      />
    </figure>
  </div>

  <div
    class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"
    style="flex-basis: 50%"
  >
    <figure class="wp-block-image size-large">
      <img
        data-od-replaced-sizes="(max-width: 1024px) 100vw, 1024px"
        data-dominant-color="8c7d58"
        data-has-transparency="false"
        style="--dominant-color: #8c7d58"
        decoding="async"
        width="1024"
        height="668"
        sizes="(width &lt;= 480px) 418px, (480px &lt; width &lt;= 600px) 400px, (600px &lt; width &lt;= 782px) 609px, (782px &lt; width) 265px, (max-width: 1024px) 100vw, 1024px"
        src="http://localhost:8888/wp-content/uploads/2024/06/bison1-1024x668.jpg"
        alt=""
        class="wp-image-13 not-transparent"
        srcset="
          http://localhost:8888/wp-content/uploads/2024/06/bison1-1024x668.jpg  1024w,
          http://localhost:8888/wp-content/uploads/2024/06/bison1-300x196.jpg    300w,
          http://localhost:8888/wp-content/uploads/2024/06/bison1-768x501.jpg    768w,
          http://localhost:8888/wp-content/uploads/2024/06/bison1-1536x1002.jpg 1536w,
          http://localhost:8888/wp-content/uploads/2024/06/bison1-2048x1336.jpg 2048w,
          http://localhost:8888/wp-content/uploads/2024/06/bison1-1568x1023.jpg 1568w
        "
      />
    </figure>
  </div>

  <div
    class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"
    style="flex-basis: 25%"
  >
    <figure class="wp-block-image size-large">
      <img
        data-od-replaced-sizes="(max-width: 1024px) 100vw, 1024px"
        data-dominant-color="7a6f31"
        data-has-transparency="false"
        style="--dominant-color: #7a6f31"
        decoding="async"
        width="1024"
        height="683"
        sizes="(width &lt;= 480px) 418px, (480px &lt; width &lt;= 600px) 400px, (600px &lt; width &lt;= 782px) 609px, (782px &lt; width) 132px, (max-width: 1024px) 100vw, 1024px"
        src="http://localhost:8888/wp-content/uploads/2024/06/bison3-1024x683.jpg"
        alt=""
        class="wp-image-11 not-transparent"
        srcset="
          http://localhost:8888/wp-content/uploads/2024/06/bison3-1024x683.jpg  1024w,
          http://localhost:8888/wp-content/uploads/2024/06/bison3-300x200.jpg    300w,
          http://localhost:8888/wp-content/uploads/2024/06/bison3-768x513.jpg    768w,
          http://localhost:8888/wp-content/uploads/2024/06/bison3-1536x1025.jpg 1536w,
          http://localhost:8888/wp-content/uploads/2024/06/bison3-2048x1367.jpg 2048w,
          http://localhost:8888/wp-content/uploads/2024/06/bison3-1568x1046.jpg 1568w
        "
      />
    </figure>
  </div>
</div>

Properly Size Images Lighthouse Audit

Before After
image image

@westonruter westonruter added [Type] Enhancement A suggestion for improvement of an existing feature [Plugin] Optimization Detective Issues for the Optimization Detective plugin [Plugin] Image Prioritizer Issues for the Image Prioritizer plugin (dependent on Optimization Detective) labels Feb 3, 2025
@westonruter westonruter added this to the image-prioritizer n.e.x.t milestone Feb 3, 2025
Copy link

github-actions bot commented Feb 3, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: westonruter <[email protected]>
Co-authored-by: felixarntz <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link

codecov bot commented Feb 3, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 66.55%. Comparing base (e845dd8) to head (4d0251a).
Report is 14 commits behind head on trunk.

Additional details and impacted files
@@            Coverage Diff             @@
##            trunk    #1840      +/-   ##
==========================================
+ Coverage   66.36%   66.55%   +0.18%     
==========================================
  Files          88       88              
  Lines        6975     6999      +24     
==========================================
+ Hits         4629     4658      +29     
+ Misses       2346     2341       -5     
Flag Coverage Δ
multisite 66.55% <100.00%> (+0.18%) ⬆️
single 37.36% <0.00%> (-0.13%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines 66 to 77
// TODO: The min-width will need to be adjusted after <https://github.com/WordPress/performance/pull/1839>.
// TODO: Consider reusing od_generate_media_query() here but note the extra parentheses should be removed from its output.
$media_queries = array();
if ( $group->get_minimum_viewport_width() !== 0 ) {
$media_queries[] = sprintf( 'min-width: %dpx', $group->get_minimum_viewport_width() );
}
if ( $group->get_maximum_viewport_width() !== PHP_INT_MAX && $group->get_maximum_viewport_width() !== null ) {
$media_queries[] = sprintf( 'max-width: %dpx', $group->get_maximum_viewport_width() );
}
if ( count( $media_queries ) > 0 ) {
$sizes[] = sprintf( '(%s) %dpx', join( ' and ', $media_queries ), round( $element_max_width ) );
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that #1839 has been merged, the resulting source size list has overlapping max/min values, for example:

(max-width: 480px) 432px, 
(min-width: 480px and max-width: 600px) 540px, 
(min-width: 600px and max-width: 782px) 704px, 
(min-width: 782px) 900px

Nevertheless, this should be fine since sizes processing stops at the first condition that matches.

However, if there aren't URL Metrics captured for a viewport group (e.g. mobile), then it could be that if the viewport is exactly 480px wide, then an image would be selected for what is intended to be the phablet viewport (which starts from 480px exclusive). If there is a different layout for the image at the next breakpoint, then this could result in the unexpected image size being chosen. For example, on desktop when images are in the columns block they appear narrower than they do on non-desktop in which case they are vertically stacked, so it's not the case that a wider viewport always results in a wider image.

To address this issue, it would seem that the CSS range syntax from #1833 should be used in the sizes attribute.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 74c2ce6

$computed_sizes = $this->compute_sizes( $context );
if ( count( $computed_sizes ) > 0 ) {
$new_sizes = join( ', ', $computed_sizes );
if ( '' !== $sizes ) {
Copy link
Member Author

@westonruter westonruter Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be preserving the original sizes at the end? It can result in some conditions that are never matched. For example, if the original sizes attribute contains (max-width: 600px) 480px, 800px and then we prefix this value with:

(max-width: 480px) 432px, 
(min-width: 480px and max-width: 600px) 540px, 
(min-width: 600px and max-width: 782px) 704px, 
(min-width: 782px) 900px

Then the original conditions will never apply because (min-width: 782px) 900px is matched first. The only scenario where they could apply is if there aren't URL Metrics gathered for some of the viewport widths, and in this case leaving the original in place would serve as a fallback. Otherwise, we could remove it if all viewport groups are populated:

Suggested change
if ( '' !== $sizes ) {
if ( '' !== $sizes && ! $context->url_metric_group_collection->is_every_group_populated() ) {

But it doesn't seem to hurt to keep the original at the end.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't the media queries generated by Image Prioritizer always cover all viewport ranges? I don't see a reason to include the original sizes if they do. Of course if only some viewport groups are populated, it would be better to have the original sizes included.

That said, I think it would be safer to only alter the sizes attribute anyway when there's sufficient samples for all viewport groups. With the media queries it includes and the original sizes media queries, I'm wary of conflicts. Since we don't want to make anything worse but only better, I would be in favor to start with only computing sizes if all viewport groups are populated.

Copy link
Member Author

@westonruter westonruter Feb 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They would only include viewport ranges for collected URL Metrics. So if nobody gets phablet or tablet traffic, then those viewport ranges would be missing. Nevertheless, the media features computed here include the minimum and the maximum. So let's say that sizes attribute is originally (max-width: 600px) 480px, 800px from WordPress and then we prepend (width <= 480px) 400px, (width > 872px) 800px since we only have URL metrics for mobile and desktop. When these are combined with the original sizes, we get:

(width <= 480px) 400px, (width > 782px) 800px, (max-width: 600px) 480px, 800px

This means that, since sizes are processed left to right:

  • Mobile viewports will get an image sized at 400px.
  • Desktop viewports will get an image sized at 800px.
  • Tablet and phablet visitors will fall back to the original sizes: (max-width: 600px) 480px, 800px, which means it will be no worse than WordPress currently does by default.

Since processing happens left-to-right, and the first condition matched is used, then there won't be a conflict.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying, that makes sense. May be worth adding an inline comment to mention that because of every viewport group providing minimum and maximum sizes, any viewport groups that are missing would simply still behave like before.

I like the idea of leaving out the original sizes value though if all viewport groups are populated, because then the original sizes would have no value at all and just look confusing in the frontend. If that's straightforward, let's add it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying, that makes sense. May be worth adding an inline comment to mention that because of every viewport group providing minimum and maximum sizes, any viewport groups that are missing would simply still behave like before.

Done in d2b9a5c

I like the idea of leaving out the original sizes value though if all viewport groups are populated, because then the original sizes would have no value at all and just look confusing in the frontend. If that's straightforward, let's add it.

Done in 93961fa. (Note my original suggestion above was incorrect in that I forgot to include the negation for the second condition, which I've now fixed in my suggestion.)

Note how now the common-lcp-image-and-lazy-loaded-image-outside-viewport-with-fully-populated-sample-data test case will omit the original sizes since all viewports are populated:

<img data-od-removed-loading="lazy" data-od-replaced-fetchpriority="low" data-od-replaced-sizes="(max-width: 600px) 480px, 800px" src="https://example.com/foo1.jpg" alt="Foo" width="1200" height="800" fetchpriority="high" srcset="https://example.com/foo1-480w.jpg 480w, https://example.com/foo1-800w.jpg 800w" sizes="(width &lt;= 480px) 432px, (480px &lt; width &lt;= 600px) 540px, (600px &lt; width &lt;= 782px) 703px, (782px &lt; width) 900px" crossorigin="anonymous">

Compare this with the only-mobile-and-desktop-groups-are-populated test case which retains the original sizes as a fallback since the phablet and tablet URL Metrics are absent:

<img data-od-removed-fetchpriority="high" data-od-replaced-sizes="(max-width: 1200px) 100vw, 1200px" data-od-xpath="/HTML/BODY/DIV[@id=&#039;page&#039;]/*[2][self::MAIN]/*[2][self::ARTICLE]/*[2][self::FIGURE]/*[1][self::IMG]" src="https://example.com/featured-image.jpg" width="1200" height="600" alt="Featured Image" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" srcset="https://example.com/featured-image-1200.jpg 1200w, https://example.com/featured-image-600.jpg 600w, https://example.com/featured-image-300.jpg 300w" sizes="(width &lt;= 480px) 360px, (782px &lt; width) 720px, (max-width: 1200px) 100vw, 1200px">

@westonruter westonruter changed the title Try: Compute responsive sizes attribute based on the width from the boundingClientRect in captured URL Metrics Compute responsive sizes attribute based on the width from the boundingClientRect in captured URL Metrics Feb 4, 2025
Comment on lines -105 to -111
$outside_viewport_rect = array_merge(
$this->get_sample_dom_rect(),
array(
'top' => 1000,
)
);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is removed because now in plugins/optimization-detective/tests/class-optimization-detective-test-helpers.php it will handle sparse boundingClientRect by merging on top of a full one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other changes similar changes in this PR are for the same reason.

),
// All are outside all initial viewports.
array(
'xpath' => '/HTML/BODY/DIV[@id=\'page\']/*[5][self::IMG]',
'isLCP' => false,
'intersectionRatio' => 0.0,
'intersectionRect' => $outside_viewport_rect,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the intersectionRect now automatically is populated to be zeroed out when the interectionRatio is 0. Previously it was not making sense to have a DOMRect containing non-zero values when the intersectionRatio was zero.

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@westonruter This looks quite good. A few questions and feedback.

$computed_sizes = $this->compute_sizes( $context );
if ( count( $computed_sizes ) > 0 ) {
$new_sizes = join( ', ', $computed_sizes );
if ( '' !== $sizes ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't the media queries generated by Image Prioritizer always cover all viewport ranges? I don't see a reason to include the original sizes if they do. Of course if only some viewport groups are populated, it would be better to have the original sizes included.

That said, I think it would be safer to only alter the sizes attribute anyway when there's sufficient samples for all viewport groups. With the media queries it includes and the original sizes media queries, I'm wary of conflicts. Since we don't want to make anything worse but only better, I would be in favor to start with only computing sizes if all viewport groups are populated.

@@ -27,7 +27,9 @@ The current optimizations include:
1. Apply lazy loading to `IMG` tags based on whether they appear in any breakpoint’s initial viewport.
2. Implement lazy loading of CSS background images added via inline `style` attributes.
3. Lazy-load `VIDEO` tags by setting the appropriate attributes based on whether they appear in the initial viewport. If a `VIDEO` is the LCP element, it gets `preload=auto`; if it is in an initial viewport, the `preload=metadata` default is left; if it is not in an initial viewport, it gets `preload=none`. Lazy-loaded videos also get initial `preload`, `autoplay`, and `poster` attributes restored when the `VIDEO` is going to enter the viewport.
5. Ensure that [`sizes=auto`](https://make.wordpress.org/core/2024/10/18/auto-sizes-for-lazy-loaded-images-in-wordpress-6-7/) is added to all lazy-loaded `IMG` elements.
5. Responsive image sizes:
1. Ensure [`sizes=auto`](https://make.wordpress.org/core/2024/10/18/auto-sizes-for-lazy-loaded-images-in-wordpress-6-7/) is added to all lazy-loaded `IMG` elements.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this text isn't new, but might be worth clarifying why that's important. Based on how it's currently phrased here, people might argue "But WordPress Core already does this!".

So maybe this can be rephrased to clarify that it's about ensuring that sizes=auto is applied correctly after Image Prioritizer has improved/fixed lazy-loading of images as done by WordPress.

Since the sizes=auto part isn't really a feature this plugin does better than WordPress (it's the lazy-loading portion it does better than WordPress, but not how it applies sizes=auto), I would put the point of computing the correct sizes above this, as it's a more powerful feature of the plugin.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like so?

Suggested change
1. Ensure [`sizes=auto`](https://make.wordpress.org/core/2024/10/18/auto-sizes-for-lazy-loaded-images-in-wordpress-6-7/) is added to all lazy-loaded `IMG` elements.
1. Ensure [`sizes=auto`](https://make.wordpress.org/core/2024/10/18/auto-sizes-for-lazy-loaded-images-in-wordpress-6-7/) is set on `IMG` tags after setting correct lazy-loading (above).

Copy link
Member

@felixarntz felixarntz Feb 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, plus moving it to #2 in the list as mentioned :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes! Done: 4d0251a

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@westonruter LGTM! Just one non-blocking comment above.

@westonruter westonruter merged commit 6459571 into trunk Feb 8, 2025
16 checks passed
@westonruter westonruter deleted the try/ip-sizes-optimization branch February 8, 2025 01:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Plugin] Image Prioritizer Issues for the Image Prioritizer plugin (dependent on Optimization Detective) [Plugin] Optimization Detective Issues for the Optimization Detective plugin [Type] Enhancement A suggestion for improvement of an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants