Skip to content
New issue

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

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

Already on GitHub? # to your account

Accurate sizes: Get accurate sizes base on ancestor block context #1818

Open
wants to merge 13 commits into
base: feature/1511-incorporate-layout-constraints-from-ancestors
Choose a base branch
from
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
50 changes: 37 additions & 13 deletions plugins/auto-sizes/includes/improve-calculate-sizes.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,11 @@ function auto_sizes_filter_image_tag( $content, array $parsed_block, WP_Block $b
*/
$filter = static function ( $sizes, $size ) use ( $block ) {

$id = isset( $block->attributes['id'] ) ? (int) $block->attributes['id'] : 0;
$alignment = $block->attributes['align'] ?? '';
$width = isset( $block->attributes['width'] ) ? (int) $block->attributes['width'] : 0;
$max_alignment = $block->context['max_alignment'] ?? '';
$id = isset( $block->attributes['id'] ) ? (int) $block->attributes['id'] : 0;
$alignment = $block->attributes['align'] ?? '';
$width = isset( $block->attributes['width'] ) ? (int) $block->attributes['width'] : 0;
$max_alignment = $block->context['max_alignment'] ?? '';
$container_relative_width = $block->context['container_relative_width'] ?? 1.0;

/*
* Update width for cover block.
Expand All @@ -108,7 +109,7 @@ function auto_sizes_filter_image_tag( $content, array $parsed_block, WP_Block $b
$size = array( 420, 420 );
}

$better_sizes = auto_sizes_calculate_better_sizes( $id, $size, $alignment, $width, $max_alignment );
$better_sizes = auto_sizes_calculate_better_sizes( $id, $size, $alignment, $width, $max_alignment, $container_relative_width );

// If better sizes can't be calculated, use the default sizes.
return false !== $better_sizes ? $better_sizes : $sizes;
Expand Down Expand Up @@ -145,14 +146,15 @@ function auto_sizes_filter_image_tag( $content, array $parsed_block, WP_Block $b
*
* @since 1.4.0
*
* @param int $id The image attachment post ID.
* @param string|array{int, int} $size Image size name or array of width and height.
* @param string $align The image alignment.
* @param int $resize_width Resize image width.
* @param string $max_alignment The maximum usable layout alignment.
* @param int $id The image attachment post ID.
* @param string|array{int, int} $size Image size name or array of width and height.
* @param string $align The image alignment.
* @param int $resize_width Resize image width.
* @param string $max_alignment The maximum usable layout alignment.
* @param float $container_relative_width Container relative width.
* @return string|false An improved sizes attribute or false if a better size cannot be calculated.
*/
function auto_sizes_calculate_better_sizes( int $id, $size, string $align, int $resize_width, string $max_alignment ) {
function auto_sizes_calculate_better_sizes( int $id, $size, string $align, int $resize_width, string $max_alignment, float $container_relative_width ) {
// Bail early if not a block theme.
if ( ! wp_is_block_theme() ) {
return false;
Expand Down Expand Up @@ -198,6 +200,17 @@ function auto_sizes_calculate_better_sizes( int $id, $size, string $align, int $

case 'wide':
$layout_width = auto_sizes_get_layout_width( 'wide' );
if (
str_ends_with( $layout_width, 'px' ) &&
( $container_relative_width > 0.0 ||
$container_relative_width < 1.0 )
) {
// First remove 'px' from width.
$layout_width = str_replace( 'px', '', $layout_width );
// Convert to float for better precision.
$layout_width = (float) $layout_width * $container_relative_width;
$layout_width = sprintf( '%dpx', (int) $layout_width );
}
break;

case 'left':
Expand All @@ -211,7 +224,15 @@ function auto_sizes_calculate_better_sizes( int $id, $size, string $align, int $
* If the layout width is in pixels, we can compare against the image width
* on the server. Otherwise, we need to rely on CSS functions.
*/
if ( str_ends_with( $layout_width, 'px' ) ) {
if (
str_ends_with( $layout_width, 'px' ) &&
( $container_relative_width > 0.0 ||
$container_relative_width < 1.0 )
) {
// First remove 'px' from width.
$layout_width = str_replace( 'px', '', $layout_width );
// Convert to float for better precision.
$layout_width = (float) $layout_width * $container_relative_width;
$layout_width = sprintf( '%dpx', min( (int) $layout_width, $image_width ) );
} else {
$layout_width = sprintf( 'min(%1$s, %2$spx)', $layout_width, $image_width );
Copy link
Member

Choose a reason for hiding this comment

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

Is it allowed to have relative values like % in the sizes attribute? Or what is the rationale for having this min() value here?

Copy link
Member Author

Choose a reason for hiding this comment

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

See #1737 for context why it was added.

Copy link
Member

@felixarntz felixarntz Apr 1, 2025

Choose a reason for hiding this comment

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

Makes sense. From that perspective though, wouldn't we be able to also use non-px values for the multiplication above? Right now the container_relative_width is only used if the unit is px. For example, if someone specified 16em and container_relative_width was 0.5, wouldn't we still be able to multiply and then use 8em?

For which units can this min() function be used in the sizes attribute? I would expect it to be for em, rem etc - but what about %? Since % needs to know the container width, I wonder whether that's even supported or not.

@joemcgill Maybe you have additional context?

Expand Down Expand Up @@ -324,7 +345,10 @@ function auto_sizes_filter_render_block_context( array $context, array $block, ?
}

// Multiply with parent's width if available.
if ( isset( $parent_block->context['container_relative_width'] ) ) {
if (
isset( $parent_block->context['container_relative_width'] ) &&
( $current_width > 0.0 || $current_width < 1.0 )
) {
$context['container_relative_width'] = $parent_block->context['container_relative_width'] * $current_width;
} else {
$context['container_relative_width'] = $current_width;
Expand Down
Loading