Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions plugins/auto-sizes/hooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ function auto_sizes_render_generator(): void {
add_filter( 'render_block_core/image', 'auto_sizes_filter_image_tag', 10, 3 );
add_filter( 'render_block_core/cover', 'auto_sizes_filter_image_tag', 10, 3 );
add_filter( 'render_block_core/post-featured-image', 'auto_sizes_filter_image_tag', 10, 3 );
add_filter( 'render_block_core/group', 'auto_sizes_add_background_image_data_attributes', 5, 2 );
add_filter( 'render_block_core/cover', 'auto_sizes_add_background_image_data_attributes', 5, 2 );
add_filter( 'get_block_type_uses_context', 'auto_sizes_filter_uses_context', 10, 2 );
add_filter( 'render_block_context', 'auto_sizes_filter_render_block_context', 10, 3 );
// @codeCoverageIgnoreEnd
56 changes: 56 additions & 0 deletions plugins/auto-sizes/includes/improve-calculate-sizes.php
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,59 @@ function auto_sizes_get_featured_image_attachment_id( int $post_id ): int {

return (int) get_post_thumbnail_id( $post_id );
}
/**
* Adds data attributes for background image attachment ID to Group and Cover blocks.
*
* This exposes the attachment ID from block attributes as data attributes on the HTML element,
* allowing Image Prioritizer to access this information without using attachment_url_to_postid().
* This is particularly important for Cover blocks that may use sizes other than "full".
*
* @param string|mixed $content The block content about to be rendered.
* @param array{ attrs?: array<string, mixed>, blockName?: string } $parsed_block The parsed block.
* @return string The updated block content.
*/
function auto_sizes_add_background_image_data_attributes( $content, array $parsed_block ): string {
if ( ! is_string( $content ) || '' === $content ) {
return '';
}

$block_name = $parsed_block['blockName'] ?? '';
$attrs = $parsed_block['attrs'] ?? array();

// Extract background image data based on block type.
$attachment_id = null;
$image_url = null;

if ( 'core/cover' === $block_name ) {
$attachment_id = $attrs['id'] ?? null;
$image_url = $attrs['url'] ?? null;
} elseif ( 'core/group' === $block_name ) {
$attachment_id = $attrs['style']['background']['backgroundImage']['id'] ?? null;
$image_url = $attrs['style']['background']['backgroundImage']['url'] ?? null;
} else {
return $content;
}

// Validate extracted data.
if (
! isset( $attachment_id, $image_url ) ||
$attachment_id <= 0 ||
'' === $image_url ||
! is_array( wp_get_attachment_metadata( $attachment_id ) )
) {
return $content;
}

// Find and update the element with background image.
$processor = new WP_HTML_Tag_Processor( $content );
while ( $processor->next_tag() ) {
$style = $processor->get_attribute( 'style' );
if ( is_string( $style ) && str_contains( $style, 'background-image:' ) && str_contains( $style, $image_url ) ) {
$processor->set_attribute( 'data-bg-attachment-id', (string) $attachment_id );
$processor->set_attribute( 'data-bg-original-url', $image_url );
return $processor->get_updated_html();
}
}

return $content;
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ public function __invoke( OD_Tag_Visitor_Context $context ): bool {
$this->add_image_preload_link( $context->link_collection, $group, $background_image_url );
}

// Reduce the background image size if URL Metrics are available.
$this->reduce_background_image_size( $background_image_url, $context );

$this->lazy_load_bg_images( $context );

return true;
Expand Down Expand Up @@ -238,4 +241,52 @@ private function lazy_load_bg_images( OD_Tag_Visitor_Context $context ): void {
$this->added_lazy_assets = true;
}
}

/**
* Reduces background image size by choosing one that fits the element dimensions more closely.
*
* This is similar to how VIDEO poster images are optimized in the Video Tag Visitor.
*
* @param non-empty-string $background_image_url Background image URL.
* @param OD_Tag_Visitor_Context $context Tag visitor context, with the cursor currently at an element with a background image.
*/
private function reduce_background_image_size( string $background_image_url, OD_Tag_Visitor_Context $context ): void {
$processor = $context->processor;
$xpath = $processor->get_xpath();

/*
* Obtain maximum width of the element exclusively from the URL Metrics group with the widest viewport width,
* which would be desktop. This prevents the situation where if URL Metrics have only so far been gathered for
* mobile viewports that an excessively-small background image would end up getting served to the first desktop visitor.
*/
$max_element_width = 0;
foreach ( $context->url_metric_group_collection->get_last_group() as $url_metric ) {
foreach ( $url_metric->get_elements() as $element ) {
if ( $element->get_xpath() === $xpath ) {
$max_element_width = max( $max_element_width, $element->get_bounding_client_rect()['width'] );
break;
}
}
}

// If the element wasn't present in any URL Metrics gathered for desktop, then abort downsizing the background image.
if ( 0 === $max_element_width ) {
return;
}

// Try to get the attachment ID from the data attribute (populated via filter from block attributes).
$attachment_id = $processor->get_attribute( 'data-bg-attachment-id' );

if ( is_numeric( $attachment_id ) && $attachment_id > 0 ) {
$smaller_image_url = wp_get_attachment_image_url( (int) $attachment_id, array( (int) $max_element_width, 0 ) );
if ( is_string( $smaller_image_url ) && $smaller_image_url !== $background_image_url ) {
// Replace the background image URL in the style attribute.
$style = $processor->get_attribute( 'style' );
if ( is_string( $style ) ) {
$updated_style = str_replace( $background_image_url, $smaller_image_url, $style );
$processor->set_attribute( 'style', $updated_style );
}
}
}
}
}
Loading