Skip to content

Commit ea33087

Browse files
Editor: Grid block responsive enhancements.
Adds styles for responsive grid layouts and fixes a block gap bug and a max column width bug. Props isabel_brison, aaronrobertshaw. Fixes #64532. git-svn-id: https://develop.svn.wordpress.org/trunk@61513 602fd350-edb4-49c9-b593-d223f7449a82
1 parent eefa4e8 commit ea33087

File tree

4 files changed

+106
-35
lines changed

4 files changed

+106
-35
lines changed

src/wp-includes/block-supports/layout.php

Lines changed: 81 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ function wp_register_layout_support( $block_type ) {
233233
* @param bool $has_block_gap_support Optional. Whether the theme has support for the block gap. Default false.
234234
* @param string|string[]|null $gap_value Optional. The block gap value to apply. Default null.
235235
* @param bool $should_skip_gap_serialization Optional. Whether to skip applying the user-defined value set in the editor. Default false.
236-
* @param string $fallback_gap_value Optional. The block gap value to apply. Default '0.5em'.
236+
* @param string|array $fallback_gap_value Optional. The block gap value to apply. If it's an array expected properties are "top" and/or "left". Default '0.5em'.
237237
* @param array|null $block_spacing Optional. Custom spacing set on the block. Default null.
238238
* @return string CSS styles on success. Else, empty string.
239239
*/
@@ -427,7 +427,12 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
427427
foreach ( $gap_sides as $gap_side ) {
428428
$process_value = $gap_value;
429429
if ( is_array( $gap_value ) ) {
430-
$process_value = $gap_value[ $gap_side ] ?? $fallback_gap_value;
430+
if ( is_array( $fallback_gap_value ) ) {
431+
$fallback_value = $fallback_gap_value[ $gap_side ] ?? reset( $fallback_gap_value );
432+
} else {
433+
$fallback_value = $fallback_gap_value;
434+
}
435+
$process_value = $gap_value[ $gap_side ] ?? $fallback_value;
431436
}
432437
// Get spacing CSS variable from preset value if provided.
433438
if ( is_string( $process_value ) && str_contains( $process_value, 'var:preset|spacing|' ) ) {
@@ -490,21 +495,14 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
490495
}
491496
}
492497
} elseif ( 'grid' === $layout_type ) {
493-
if ( ! empty( $layout['columnCount'] ) ) {
494-
$layout_styles[] = array(
495-
'selector' => $selector,
496-
'declarations' => array( 'grid-template-columns' => 'repeat(' . $layout['columnCount'] . ', minmax(0, 1fr))' ),
497-
);
498+
/*
499+
* If the gap value is an array, we use the "left" value because it represents the vertical gap, which
500+
* is the relevant one for computation of responsive grid columns.
501+
*/
502+
if ( is_array( $fallback_gap_value ) ) {
503+
$responsive_gap_value = $fallback_gap_value['left'] ?? reset( $fallback_gap_value );
498504
} else {
499-
$minimum_column_width = ! empty( $layout['minimumColumnWidth'] ) ? $layout['minimumColumnWidth'] : '12rem';
500-
501-
$layout_styles[] = array(
502-
'selector' => $selector,
503-
'declarations' => array(
504-
'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))',
505-
'container-type' => 'inline-size',
506-
),
507-
);
505+
$responsive_gap_value = $fallback_gap_value;
508506
}
509507

510508
if ( $has_block_gap_support && isset( $gap_value ) ) {
@@ -514,7 +512,12 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
514512
foreach ( $gap_sides as $gap_side ) {
515513
$process_value = $gap_value;
516514
if ( is_array( $gap_value ) ) {
517-
$process_value = $gap_value[ $gap_side ] ?? $fallback_gap_value;
515+
if ( is_array( $fallback_gap_value ) ) {
516+
$fallback_value = $fallback_gap_value[ $gap_side ] ?? reset( $fallback_gap_value );
517+
} else {
518+
$fallback_value = $fallback_gap_value;
519+
}
520+
$process_value = $gap_value[ $gap_side ] ?? $fallback_value;
518521
}
519522
// Get spacing CSS variable from preset value if provided.
520523
if ( is_string( $process_value ) && str_contains( $process_value, 'var:preset|spacing|' ) ) {
@@ -524,14 +527,58 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
524527
}
525528
$combined_gap_value .= "$process_value ";
526529
}
527-
$gap_value = trim( $combined_gap_value );
530+
$gap_value = trim( $combined_gap_value );
531+
$responsive_gap_value = $gap_value;
532+
}
528533

529-
if ( null !== $gap_value && ! $should_skip_gap_serialization ) {
534+
// Ensure 0 values have a unit so they work in calc().
535+
if ( '0' === $responsive_gap_value || 0 === $responsive_gap_value ) {
536+
$responsive_gap_value = '0px';
537+
}
538+
539+
if ( ! empty( $layout['columnCount'] ) && ! empty( $layout['minimumColumnWidth'] ) ) {
540+
$max_value = 'max(min(' . $layout['minimumColumnWidth'] . ', 100%), (100% - (' . $responsive_gap_value . ' * (' . $layout['columnCount'] . ' - 1))) /' . $layout['columnCount'] . ')';
541+
$layout_styles[] = array(
542+
'selector' => $selector,
543+
'declarations' => array(
544+
'grid-template-columns' => 'repeat(auto-fill, minmax(' . $max_value . ', 1fr))',
545+
'container-type' => 'inline-size',
546+
),
547+
);
548+
if ( ! empty( $layout['rowCount'] ) ) {
530549
$layout_styles[] = array(
531550
'selector' => $selector,
532-
'declarations' => array( 'gap' => $gap_value ),
551+
'declarations' => array( 'grid-template-rows' => 'repeat(' . $layout['rowCount'] . ', minmax(1rem, auto))' ),
533552
);
534553
}
554+
} elseif ( ! empty( $layout['columnCount'] ) ) {
555+
$layout_styles[] = array(
556+
'selector' => $selector,
557+
'declarations' => array( 'grid-template-columns' => 'repeat(' . $layout['columnCount'] . ', minmax(0, 1fr))' ),
558+
);
559+
if ( ! empty( $layout['rowCount'] ) ) {
560+
$layout_styles[] = array(
561+
'selector' => $selector,
562+
'declarations' => array( 'grid-template-rows' => 'repeat(' . $layout['rowCount'] . ', minmax(1rem, auto))' ),
563+
);
564+
}
565+
} else {
566+
$minimum_column_width = ! empty( $layout['minimumColumnWidth'] ) ? $layout['minimumColumnWidth'] : '12rem';
567+
568+
$layout_styles[] = array(
569+
'selector' => $selector,
570+
'declarations' => array(
571+
'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))',
572+
'container-type' => 'inline-size',
573+
),
574+
);
575+
}
576+
577+
if ( $has_block_gap_support && null !== $gap_value && ! $should_skip_gap_serialization ) {
578+
$layout_styles[] = array(
579+
'selector' => $selector,
580+
'declarations' => array( 'gap' => $gap_value ),
581+
);
535582
}
536583
}
537584

@@ -568,6 +615,8 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
568615
* @return string Filtered block content.
569616
*/
570617
function wp_render_layout_support_flag( $block_content, $block ) {
618+
static $global_styles = null;
619+
571620
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
572621
$block_supports_layout = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__experimentalLayout', false );
573622
$child_layout = $block['attrs']['style']['layout'] ?? null;
@@ -804,6 +853,18 @@ function wp_render_layout_support_flag( $block_content, $block ) {
804853
$block_gap = $global_settings['spacing']['blockGap'] ?? null;
805854
$has_block_gap_support = isset( $block_gap );
806855

856+
// Get default blockGap value from global styles for use in layouts like grid.
857+
// Check block-specific styles first, then fall back to root styles.
858+
$block_name = $block['blockName'] ?? '';
859+
if ( null === $global_styles ) {
860+
$global_styles = wp_get_global_styles();
861+
}
862+
$global_block_gap_value = $global_styles['blocks'][ $block_name ]['spacing']['blockGap'] ?? ( $global_styles['spacing']['blockGap'] ?? null );
863+
864+
if ( null !== $global_block_gap_value ) {
865+
$fallback_gap_value = $global_block_gap_value;
866+
}
867+
807868
/*
808869
* Generates a unique ID based on all the data required to obtain the
809870
* corresponding layout style. Keeps the CSS class names the same

tests/phpunit/data/blocks/fixtures/core__columns.server.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
<div class="wp-block-columns has-3-columns is-layout-flex wp-container-1d6595d7 wp-block-columns-is-layout-flex">
2+
<div class="wp-block-columns has-3-columns is-layout-flex wp-container-1f761849 wp-block-columns-is-layout-flex">
33

44
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
55

tests/phpunit/data/blocks/fixtures/core__columns__deprecated.server.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
<div class="wp-block-columns has-3-columns is-layout-flex wp-container-1d6595d7 wp-block-columns-is-layout-flex">
2+
<div class="wp-block-columns has-3-columns is-layout-flex wp-container-1f761849 wp-block-columns-is-layout-flex">
33

44
<p class="layout-column-1">Column One, Paragraph One</p>
55

tests/phpunit/tests/block-supports/layout.php

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ public function data_layout_support_flag_renders_classnames_on_wrapper() {
293293
),
294294
),
295295
),
296-
'expected_output' => '<div class="wp-block-group is-horizontal is-nowrap is-layout-flex wp-container-core-group-is-layout-67f0b8e2 wp-block-group-is-layout-flex"></div>',
296+
'expected_output' => '<div class="wp-block-group is-horizontal is-nowrap is-layout-flex wp-container-core-group-is-layout-ee7b5020 wp-block-group-is-layout-flex"></div>',
297297
),
298298
'single wrapper block layout with grid type' => array(
299299
'args' => array(
@@ -312,7 +312,7 @@ public function data_layout_support_flag_renders_classnames_on_wrapper() {
312312
),
313313
),
314314
),
315-
'expected_output' => '<div class="wp-block-group is-layout-grid wp-container-core-group-is-layout-9649a0d9 wp-block-group-is-layout-grid"></div>',
315+
'expected_output' => '<div class="wp-block-group is-layout-grid wp-container-core-group-is-layout-9d260ee2 wp-block-group-is-layout-grid"></div>',
316316
),
317317
'skip classname output if block does not support layout and there are no child layout classes to be output' => array(
318318
'args' => array(
@@ -542,9 +542,19 @@ public function test_layout_support_flag_renders_consistent_container_hash( $blo
542542
$processor = new WP_HTML_Tag_Processor( $output );
543543
$processor->next_tag();
544544

545-
$this->assertTrue(
546-
$processor->has_class( $expected_class ),
547-
"Expected class '$expected_class' not found in the rendered output, probably because of a different hash."
545+
// Extract the actual container class from the output for better error messages.
546+
$actual_class = '';
547+
foreach ( $processor->class_list() as $class_name ) {
548+
if ( str_starts_with( $class_name, 'wp-container-core-group-is-layout-' ) ) {
549+
$actual_class = $class_name;
550+
break;
551+
}
552+
}
553+
554+
$this->assertEquals(
555+
$expected_class,
556+
$actual_class,
557+
'Expected class not found in the rendered output, probably because of a different hash.'
548558
);
549559
}
550560

@@ -566,7 +576,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
566576
),
567577
),
568578
),
569-
'expected_class' => 'wp-container-core-group-is-layout-c5c7d83f',
579+
'expected_class' => 'wp-container-core-group-is-layout-a6248535',
570580
),
571581
'default type block gap 24px' => array(
572582
'block_attributes' => array(
@@ -579,7 +589,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
579589
),
580590
),
581591
),
582-
'expected_class' => 'wp-container-core-group-is-layout-634f0b9d',
592+
'expected_class' => 'wp-container-core-group-is-layout-61b496ee',
583593
),
584594
'constrained type justified left' => array(
585595
'block_attributes' => array(
@@ -588,7 +598,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
588598
'justifyContent' => 'left',
589599
),
590600
),
591-
'expected_class' => 'wp-container-core-group-is-layout-12dd3699',
601+
'expected_class' => 'wp-container-core-group-is-layout-54d22900',
592602
),
593603
'constrained type justified right' => array(
594604
'block_attributes' => array(
@@ -597,7 +607,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
597607
'justifyContent' => 'right',
598608
),
599609
),
600-
'expected_class' => 'wp-container-core-group-is-layout-f1f2ed93',
610+
'expected_class' => 'wp-container-core-group-is-layout-2910ada7',
601611
),
602612
'flex type horizontal' => array(
603613
'block_attributes' => array(
@@ -607,7 +617,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
607617
'flexWrap' => 'nowrap',
608618
),
609619
),
610-
'expected_class' => 'wp-container-core-group-is-layout-2487dcaa',
620+
'expected_class' => 'wp-container-core-group-is-layout-f5d79bea',
611621
),
612622
'flex type vertical' => array(
613623
'block_attributes' => array(
@@ -616,15 +626,15 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
616626
'orientation' => 'vertical',
617627
),
618628
),
619-
'expected_class' => 'wp-container-core-group-is-layout-fe9cc265',
629+
'expected_class' => 'wp-container-core-group-is-layout-2c90304e',
620630
),
621631
'grid type' => array(
622632
'block_attributes' => array(
623633
'layout' => array(
624634
'type' => 'grid',
625635
),
626636
),
627-
'expected_class' => 'wp-container-core-group-is-layout-478b6e6b',
637+
'expected_class' => 'wp-container-core-group-is-layout-5a23bf8e',
628638
),
629639
'grid type 3 columns' => array(
630640
'block_attributes' => array(
@@ -633,7 +643,7 @@ public function data_layout_support_flag_renders_consistent_container_hash() {
633643
'columnCount' => 3,
634644
),
635645
),
636-
'expected_class' => 'wp-container-core-group-is-layout-d3b710ac',
646+
'expected_class' => 'wp-container-core-group-is-layout-cda6dc4f',
637647
),
638648
);
639649
}

0 commit comments

Comments
 (0)