From 4a7841d60ef0ee679ea84874844c2e54b6061a67 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Mon, 15 Jun 2026 13:07:43 +1000 Subject: [PATCH] Fix flex child fixed width and introduce max width option --- src/wp-includes/block-supports/layout.php | 38 ++++- tests/phpunit/tests/block-supports/layout.php | 156 ++++++++++++++++++ 2 files changed, 191 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/block-supports/layout.php b/src/wp-includes/block-supports/layout.php index 2f7eebd4e2cda..57fac4258c46c 100644 --- a/src/wp-includes/block-supports/layout.php +++ b/src/wp-includes/block-supports/layout.php @@ -116,13 +116,45 @@ function wp_get_child_layout_style_rules( $selector, $child_layout, $parent_layo return array_key_exists( $property, $viewport_overrides ); }; - $self_stretch = $child_layout['selfStretch'] ?? null; + $self_stretch = $child_layout['selfStretch'] ?? null; + $base_self_stretch = $base_child_layout['selfStretch'] ?? null; + + /* + * These are the serialized `selfStretch` values. `max` used to be called + * "Fixed" in the UI, but was renamed and replaced by `fixedNoShrink`. + */ + $flex_child_layout_values = array( + 'fit' => 'fit', + 'grow' => 'fill', + 'max' => 'fixed', + 'fixed' => 'fixedNoShrink', + ); + $flex_size_values = array( + $flex_child_layout_values['max'], + $flex_child_layout_values['fixed'], + ); if ( null === $viewport_overrides || $has_viewport_property_override( 'selfStretch' ) || $has_viewport_property_override( 'flexSize' ) ) { - if ( 'fixed' === $self_stretch && isset( $child_layout['flexSize'] ) ) { + if ( + null !== $viewport_overrides && + ( $flex_child_layout_values['fit'] === $self_stretch || $flex_child_layout_values['grow'] === $self_stretch ) && + in_array( $base_self_stretch, $flex_size_values, true ) && + isset( $base_child_layout['flexSize'] ) + ) { + $child_layout_declarations['flex-basis'] = 'unset'; + if ( $flex_child_layout_values['fixed'] === $base_self_stretch ) { + $child_layout_declarations['flex-shrink'] = 'unset'; + } + } + if ( in_array( $self_stretch, $flex_size_values, true ) && isset( $child_layout['flexSize'] ) ) { $child_layout_declarations['flex-basis'] = $child_layout['flexSize']; + if ( $flex_child_layout_values['fixed'] === $self_stretch ) { + $child_layout_declarations['flex-shrink'] = '0'; + } elseif ( null !== $viewport_overrides && $flex_child_layout_values['fixed'] === $base_self_stretch ) { + $child_layout_declarations['flex-shrink'] = 'unset'; + } $child_layout_declarations['box-sizing'] = 'border-box'; - } elseif ( 'fill' === $self_stretch ) { + } elseif ( $flex_child_layout_values['grow'] === $self_stretch ) { $child_layout_declarations['flex-grow'] = '1'; } } diff --git a/tests/phpunit/tests/block-supports/layout.php b/tests/phpunit/tests/block-supports/layout.php index f47a7a3e35d2b..a7b6d519dd4e2 100644 --- a/tests/phpunit/tests/block-supports/layout.php +++ b/tests/phpunit/tests/block-supports/layout.php @@ -447,6 +447,162 @@ public function data_restore_group_inner_container() { ); } + /** + * Check that wp_get_child_layout_style_rules() renders flex child sizing styles. + * + * @dataProvider data_wp_get_child_layout_style_rules + * + * @covers ::wp_get_child_layout_style_rules + * + * @param array $child_layout Child layout values. + * @param array|null $viewport_overrides Optional child viewport layout overrides. + * @param array $expected_output The expected output. + */ + public function test_wp_get_child_layout_style_rules( $child_layout, $viewport_overrides, $expected_output ) { + $actual_output = wp_get_child_layout_style_rules( + '.wp-container-content-test', + $child_layout, + array(), + $viewport_overrides + ); + + $this->assertSame( $expected_output, $actual_output ); + } + + /** + * Data provider for test_wp_get_child_layout_style_rules(). + * + * @return array + */ + public function data_wp_get_child_layout_style_rules() { + return array( + 'legacy fixed sizing remains shrinkable' => array( + 'child_layout' => array( + 'selfStretch' => 'fixed', + 'flexSize' => '320px', + ), + 'viewport_overrides' => null, + 'expected_output' => array( + array( + 'selector' => '.wp-container-content-test', + 'declarations' => array( + 'flex-basis' => '320px', + 'box-sizing' => 'border-box', + ), + ), + ), + ), + 'fixed sizing can opt out of shrinking' => array( + 'child_layout' => array( + 'selfStretch' => 'fixedNoShrink', + 'flexSize' => '320px', + ), + 'viewport_overrides' => null, + 'expected_output' => array( + array( + 'selector' => '.wp-container-content-test', + 'declarations' => array( + 'flex-basis' => '320px', + 'flex-shrink' => '0', + 'box-sizing' => 'border-box', + ), + ), + ), + ), + 'viewport overrides can switch fixedNoShrink to max' => array( + 'child_layout' => array( + 'selfStretch' => 'fixedNoShrink', + 'flexSize' => '320px', + ), + 'viewport_overrides' => array( + 'selfStretch' => 'fixed', + ), + 'expected_output' => array( + array( + 'selector' => '.wp-container-content-test', + 'declarations' => array( + 'flex-basis' => '320px', + 'flex-shrink' => 'unset', + 'box-sizing' => 'border-box', + ), + ), + ), + ), + 'viewport overrides can switch fixedNoShrink to fit' => array( + 'child_layout' => array( + 'selfStretch' => 'fixedNoShrink', + 'flexSize' => '320px', + ), + 'viewport_overrides' => array( + 'selfStretch' => 'fit', + ), + 'expected_output' => array( + array( + 'selector' => '.wp-container-content-test', + 'declarations' => array( + 'flex-basis' => 'unset', + 'flex-shrink' => 'unset', + ), + ), + ), + ), + 'viewport overrides can switch fixed to fit' => array( + 'child_layout' => array( + 'selfStretch' => 'fixed', + 'flexSize' => '320px', + ), + 'viewport_overrides' => array( + 'selfStretch' => 'fit', + ), + 'expected_output' => array( + array( + 'selector' => '.wp-container-content-test', + 'declarations' => array( + 'flex-basis' => 'unset', + ), + ), + ), + ), + 'viewport overrides can switch fixedNoShrink to grow' => array( + 'child_layout' => array( + 'selfStretch' => 'fixedNoShrink', + 'flexSize' => '320px', + ), + 'viewport_overrides' => array( + 'selfStretch' => 'fill', + ), + 'expected_output' => array( + array( + 'selector' => '.wp-container-content-test', + 'declarations' => array( + 'flex-basis' => 'unset', + 'flex-shrink' => 'unset', + 'flex-grow' => '1', + ), + ), + ), + ), + 'viewport overrides can switch fixed to grow' => array( + 'child_layout' => array( + 'selfStretch' => 'fixed', + 'flexSize' => '320px', + ), + 'viewport_overrides' => array( + 'selfStretch' => 'fill', + ), + 'expected_output' => array( + array( + 'selector' => '.wp-container-content-test', + 'declarations' => array( + 'flex-basis' => 'unset', + 'flex-grow' => '1', + ), + ), + ), + ), + ); + } + /** * Checks that `wp_add_parent_layout_to_parsed_block` adds the parent layout attribute to the block object. *