Make WordPress Core

Changeset 62513


Ignore:
Timestamp:
06/17/2026 01:17:11 AM (4 months ago)
Author:
isabel_brison
Message:

Editor: add support for aspect ratio and related controls in viewport states.

Enables responsive aspect ratio, scale, width, height and min-height in Image, Featured image and Cover blocks.

Props isabel_brison, ramonopoly.
See #65164.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/block-supports/dimensions.php

    r61620 r62513  
    8888
    8989/**
     90 * Checks whether an aspectRatio block-support value is explicitly set.
     91 *
     92 * @since 7.1.0
     93 * @access private
     94 *
     95 * @param mixed $aspect_ratio Aspect-ratio value.
     96 * @return bool Whether the value is an explicit aspect ratio.
     97 */
     98function wp_is_explicit_aspect_ratio_value( $aspect_ratio ) {
     99        if ( ! is_string( $aspect_ratio ) && ! is_numeric( $aspect_ratio ) ) {
     100                return false;
     101        }
     102
     103        $aspect_ratio = strtolower( trim( (string) $aspect_ratio ) );
     104
     105        return '' !== $aspect_ratio && 'auto' !== $aspect_ratio;
     106}
     107
     108/**
    90109 * Renders server-side dimensions styles to the block wrapper.
    91110 * This block support uses the `render_block` hook to ensure that
    … …  
    114133        $dimensions_block_styles['aspectRatio'] = $block_attributes['style']['dimensions']['aspectRatio'] ?? null;
    115134
    116         // To ensure the aspect ratio does not get overridden by `minHeight` unset any existing rule.
     135        // To ensure the aspect ratio does not get overridden by `minHeight` or `height` unset any existing rule.
    117136        if (
    118                 isset( $dimensions_block_styles['aspectRatio'] )
     137                wp_is_explicit_aspect_ratio_value( $dimensions_block_styles['aspectRatio'] )
    119138        ) {
    120139                $dimensions_block_styles['minHeight'] = 'unset';
     140                $dimensions_block_styles['height']    = 'unset';
    121141        } elseif (
    122142                isset( $block_attributes['style']['dimensions']['minHeight'] ) ||
    … …  
    150170                                        if (
    151171                                                str_contains( $class_name, 'aspect-ratio' ) &&
    152                                                 ! isset( $block_attributes['style']['dimensions']['aspectRatio'] )
     172                                                ! wp_is_explicit_aspect_ratio_value( $block_attributes['style']['dimensions']['aspectRatio'] ?? null )
    153173                                        ) {
    154174                                                continue;
  • trunk/src/wp-includes/block-supports/states.php

    r62506 r62513  
    132132
    133133        return $declarations;
     134}
     135
     136/**
     137 * Adds fallback dimension styles for aspectRatio and height block-support values.
     138 *
     139 * @since 7.1.0
     140 *
     141 * @param array $state_style State style object.
     142 * @return array State style object with fallback dimension styles applied where needed.
     143 */
     144function wp_get_state_style_with_fallback_dimension_styles( $state_style ) {
     145        if ( ! is_array( $state_style ) ) {
     146                return $state_style;
     147        }
     148
     149        $dimensions = isset( $state_style['dimensions'] ) && is_array( $state_style['dimensions'] )
     150                ? $state_style['dimensions']
     151                : array();
     152
     153        if ( empty( $dimensions ) ) {
     154                return $state_style;
     155        }
     156
     157        if ( wp_is_explicit_aspect_ratio_value( $dimensions['aspectRatio'] ?? null ) ) {
     158                return array_replace_recursive(
     159                        $state_style,
     160                        array(
     161                                'dimensions' => array(
     162                                        'minHeight' => 'unset',
     163                                        'height'    => 'unset',
     164                                ),
     165                        )
     166                );
     167        }
     168
     169        $has_min_height = isset( $dimensions['minHeight'] ) && ( is_string( $dimensions['minHeight'] ) || is_numeric( $dimensions['minHeight'] ) ) && '' !== trim( (string) $dimensions['minHeight'] );
     170        $has_height     = isset( $dimensions['height'] ) && ( is_string( $dimensions['height'] ) || is_numeric( $dimensions['height'] ) ) && '' !== trim( (string) $dimensions['height'] );
     171
     172        if ( $has_min_height || $has_height ) {
     173                return array_replace_recursive(
     174                        $state_style,
     175                        array(
     176                                'dimensions' => array(
     177                                        'aspectRatio' => 'unset',
     178                                ),
     179                        )
     180                );
     181        }
     182
     183        return $state_style;
    134184}
    135185
    … …  
    268318
    269319                foreach ( wp_get_state_style_groups( $state_style, $block_selectors ) as $group ) {
     320                        $style    = wp_get_state_style_with_fallback_dimension_styles( $group['style'] );
    270321                        $compiled = wp_style_engine_get_styles(
    271                                 wp_normalize_state_style_for_css_output( $group['style'] )
     322                                wp_normalize_state_style_for_css_output( $style )
    272323                        );
    273324
    … …  
    491542        $style_rules = array();
    492543        foreach ( $css_rules as $rule ) {
    493                 $declarations = array();
    494                 foreach ( $rule['declarations'] as $property => $value ) {
     544                $declarations = $rule['declarations'];
     545                foreach ( $declarations as $property => $value ) {
    495546                        $declarations[ $property ] = is_string( $value ) && str_contains( $value, '!important' )
    496547                                ? $value
  • trunk/src/wp-includes/style-engine/class-wp-style-engine.php

    r61632 r62513  
    230230                                ),
    231231                        ),
     232                        'objectFit'   => array(
     233                                'property_keys' => array(
     234                                        'default' => 'object-fit',
     235                                ),
     236                                'path'          => array( 'dimensions', 'objectFit' ),
     237                        ),
    232238                        'width'       => array(
    233239                                'property_keys' => array(
  • trunk/tests/phpunit/tests/block-supports/states.php

    r62506 r62513  
    222222
    223223                $this->assertSame( $input, $actual );
     224        }
     225
     226        /**
     227         * Tests that fallback dimension styles are added for aspect ratio.
     228         *
     229         * @covers ::wp_get_state_style_with_fallback_dimension_styles
     230         *
     231         * @ticket 65239
     232         */
     233        public function test_adds_fallback_dimension_styles_for_aspect_ratio() {
     234                $actual = wp_get_state_style_with_fallback_dimension_styles(
     235                        array(
     236                                'dimensions' => array(
     237                                        'aspectRatio' => '16/9',
     238                                ),
     239                        )
     240                );
     241
     242                $this->assertSame(
     243                        array(
     244                                'dimensions' => array(
     245                                        'aspectRatio' => '16/9',
     246                                        'minHeight'   => 'unset',
     247                                        'height'      => 'unset',
     248                                ),
     249                        ),
     250                        $actual
     251                );
     252        }
     253
     254        /**
     255         * Tests that fallback dimension styles are not added for the default aspect ratio.
     256         *
     257         * @covers ::wp_get_state_style_with_fallback_dimension_styles
     258         *
     259         * @ticket 65239
     260         */
     261        public function test_does_not_add_fallback_dimension_styles_for_default_aspect_ratio() {
     262                $actual = wp_get_state_style_with_fallback_dimension_styles(
     263                        array(
     264                                'dimensions' => array(
     265                                        'aspectRatio' => 'auto',
     266                                ),
     267                        )
     268                );
     269
     270                $this->assertSame(
     271                        array(
     272                                'dimensions' => array(
     273                                        'aspectRatio' => 'auto',
     274                                ),
     275                        ),
     276                        $actual
     277                );
     278        }
     279
     280        /**
     281         * Tests that fallback aspectRatio styles are added for height.
     282         *
     283         * @covers ::wp_get_state_style_with_fallback_dimension_styles
     284         *
     285         * @ticket 65239
     286         */
     287        public function test_adds_fallback_aspect_ratio_style_for_height() {
     288                $actual = wp_get_state_style_with_fallback_dimension_styles(
     289                        array(
     290                                'dimensions' => array(
     291                                        'height' => '20rem',
     292                                ),
     293                        )
     294                );
     295
     296                $this->assertSame(
     297                        array(
     298                                'dimensions' => array(
     299                                        'height'      => '20rem',
     300                                        'aspectRatio' => 'unset',
     301                                ),
     302                        ),
     303                        $actual
     304                );
    224305        }
    225306
  • trunk/tests/phpunit/tests/block-supports/wpRenderDimensionsSupport.php

    r61008 r62513  
    122122        public function data_dimensions_block_support() {
    123123                return array(
    124                         'aspect ratio style is applied, with min-height unset' => array(
     124                        'aspect ratio style is applied, with min-height and height unset' => array(
    125125                                'theme_name'          => 'block-theme-child-with-fluid-typography',
    126126                                'block_name'          => 'test/dimensions-rules-are-output',
    … …  
    131131                                        'aspectRatio' => '16/9',
    132132                                ),
    133                                 'expected_wrapper'    => '<div class="has-aspect-ratio" style="aspect-ratio:16/9;min-height:unset;">Content</div>',
     133                                'expected_wrapper'    => '<div class="has-aspect-ratio" style="aspect-ratio:16/9;height:unset;min-height:unset;">Content</div>',
    134134                                'wrapper'             => '<div>Content</div>',
    135135                        ),
    … …  
    143143                                        'aspectRatio' => '16/9',
    144144                                ),
    145                                 'expected_wrapper'    => '<div class="wp-block-test has-aspect-ratio" style="color:red;aspect-ratio:16/9;min-height:unset;">Content</div>',
     145                                'expected_wrapper'    => '<div class="wp-block-test has-aspect-ratio" style="color:red;aspect-ratio:16/9;height:unset;min-height:unset;">Content</div>',
    146146                                'wrapper'             => '<div class="wp-block-test" style="color:red;">Content</div>',
    147147                        ),
    … …  
    172172                );
    173173        }
     174
     175        /**
     176         * Tests that fallback height styles are not added for the default aspect ratio.
     177         *
     178         * @ticket 65239
     179         *
     180         * @covers ::wp_render_dimensions_support
     181         */
     182        public function test_default_aspect_ratio_does_not_unset_height_styles() {
     183                $this->test_block_name = 'test/default-aspect-ratio-does-not-unset-height-styles';
     184                register_block_type(
     185                        $this->test_block_name,
     186                        array(
     187                                'api_version' => 3,
     188                                'attributes'  => array(
     189                                        'style' => array(
     190                                                'type' => 'object',
     191                                        ),
     192                                ),
     193                                'supports'    => array(
     194                                        'dimensions' => array(
     195                                                'aspectRatio' => true,
     196                                        ),
     197                                ),
     198                        )
     199                );
     200
     201                $actual = wp_render_dimensions_support(
     202                        '<div class="wp-block-test">Hello</div>',
     203                        array(
     204                                'blockName' => $this->test_block_name,
     205                                'attrs'     => array(
     206                                        'style' => array(
     207                                                'dimensions' => array(
     208                                                        'aspectRatio' => 'auto',
     209                                                ),
     210                                        ),
     211                                ),
     212                        )
     213                );
     214
     215                $this->assertStringNotContainsString( 'height:unset', $actual );
     216                $this->assertStringNotContainsString( 'min-height:unset', $actual );
     217        }
    174218}
  • trunk/tests/phpunit/tests/style-engine/styleEngine.php

    r61631 r62513  
    123123                                'block_styles'    => array(
    124124                                        'dimensions' => array(
    125                                                 'width'  => 'var:preset|dimension|large',
    126                                                 'height' => 'var:preset|dimension|modestly-small',
    127                                         ),
    128                                 ),
    129                                 'options'         => null,
    130                                 'expected_output' => array(
    131                                         'css'          => 'height:var(--wp--preset--dimension--modestly-small);width:var(--wp--preset--dimension--large);',
    132                                         'declarations' => array(
    133                                                 'height' => 'var(--wp--preset--dimension--modestly-small)',
    134                                                 'width'  => 'var(--wp--preset--dimension--large)',
     125                                                'width'     => 'var:preset|dimension|large',
     126                                                'height'    => 'var:preset|dimension|modestly-small',
     127                                                'objectFit' => 'cover',
     128                                        ),
     129                                ),
     130                                'options'         => null,
     131                                'expected_output' => array(
     132                                        'css'          => 'height:var(--wp--preset--dimension--modestly-small);object-fit:cover;width:var(--wp--preset--dimension--large);',
     133                                        'declarations' => array(
     134                                                'height'     => 'var(--wp--preset--dimension--modestly-small)',
     135                                                'object-fit' => 'cover',
     136                                                'width'      => 'var(--wp--preset--dimension--large)',
    135137                                        ),
    136138                                ),
Note: See TracChangeset for help on using the changeset viewer.