@@ -489,7 +489,10 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
489489
490490 $ layout_styles [] = array (
491491 'selector ' => $ selector ,
492- 'declarations ' => array ( 'grid-template-columns ' => 'repeat(auto-fill, minmax(min( ' . $ minimum_column_width . ', 100%), 1fr)) ' ),
492+ 'declarations ' => array (
493+ 'grid-template-columns ' => 'repeat(auto-fill, minmax(min( ' . $ minimum_column_width . ', 100%), 1fr)) ' ,
494+ 'container-type ' => 'inline-size ' ,
495+ ),
493496 );
494497 }
495498
@@ -555,45 +558,102 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
555558function wp_render_layout_support_flag ( $ block_content , $ block ) {
556559 $ block_type = WP_Block_Type_Registry::get_instance ()->get_registered ( $ block ['blockName ' ] );
557560 $ block_supports_layout = block_has_support ( $ block_type , 'layout ' , false ) || block_has_support ( $ block_type , '__experimentalLayout ' , false );
558- $ layout_from_parent = isset ( $ block ['attrs ' ]['style ' ]['layout ' ][ ' selfStretch ' ] ) ? $ block ['attrs ' ]['style ' ]['layout ' ][ ' selfStretch ' ] : null ;
561+ $ child_layout = isset ( $ block ['attrs ' ]['style ' ]['layout ' ] ) ? $ block ['attrs ' ]['style ' ]['layout ' ] : null ;
559562
560- if ( ! $ block_supports_layout && ! $ layout_from_parent ) {
563+ if ( ! $ block_supports_layout && ! $ child_layout ) {
561564 return $ block_content ;
562565 }
563566
564567 $ outer_class_names = array ();
565568
566- if ( 'fixed ' === $ layout_from_parent || 'fill ' === $ layout_from_parent ) {
567- $ container_content_class = wp_unique_id ( 'wp-container-content- ' );
569+ // Child layout specific logic.
570+ if ( $ child_layout ) {
571+ $ container_content_class = wp_unique_prefixed_id ( 'wp-container-content- ' );
572+ $ child_layout_declarations = array ();
573+ $ child_layout_styles = array ();
568574
569- $ child_layout_styles = array ();
575+ $ self_stretch = isset ( $ child_layout ['selfStretch ' ] ) ? $ child_layout ['selfStretch ' ] : null ;
576+
577+ if ( 'fixed ' === $ self_stretch && isset ( $ child_layout ['flexSize ' ] ) ) {
578+ $ child_layout_declarations ['flex-basis ' ] = $ child_layout ['flexSize ' ];
579+ $ child_layout_declarations ['box-sizing ' ] = 'border-box ' ;
580+ } elseif ( 'fill ' === $ self_stretch ) {
581+ $ child_layout_declarations ['flex-grow ' ] = '1 ' ;
582+ }
583+
584+ if ( isset ( $ child_layout ['columnSpan ' ] ) ) {
585+ $ column_span = $ child_layout ['columnSpan ' ];
586+ $ child_layout_declarations ['grid-column ' ] = "span $ column_span " ;
587+ }
588+ if ( isset ( $ child_layout ['rowSpan ' ] ) ) {
589+ $ row_span = $ child_layout ['rowSpan ' ];
590+ $ child_layout_declarations ['grid-row ' ] = "span $ row_span " ;
591+ }
592+ $ child_layout_styles [] = array (
593+ 'selector ' => ". $ container_content_class " ,
594+ 'declarations ' => $ child_layout_declarations ,
595+ );
596+
597+ /*
598+ * If columnSpan is set, and the parent grid is responsive, i.e. if it has a minimumColumnWidth set,
599+ * the columnSpan should be removed on small grids. If there's a minimumColumnWidth, the grid is responsive.
600+ * But if the minimumColumnWidth value wasn't changed, it won't be set. In that case, if columnCount doesn't
601+ * exist, we can assume that the grid is responsive.
602+ */
603+ if ( isset ( $ child_layout ['columnSpan ' ] ) && ( isset ( $ block ['parentLayout ' ]['minimumColumnWidth ' ] ) || ! isset ( $ block ['parentLayout ' ]['columnCount ' ] ) ) ) {
604+ $ column_span_number = floatval ( $ child_layout ['columnSpan ' ] );
605+ $ parent_column_width = isset ( $ block ['parentLayout ' ]['minimumColumnWidth ' ] ) ? $ block ['parentLayout ' ]['minimumColumnWidth ' ] : '12rem ' ;
606+ $ parent_column_value = floatval ( $ parent_column_width );
607+ $ parent_column_unit = explode ( $ parent_column_value , $ parent_column_width );
608+
609+ /*
610+ * If there is no unit, the width has somehow been mangled so we reset both unit and value
611+ * to defaults.
612+ * Additionally, the unit should be one of px, rem or em, so that also needs to be checked.
613+ */
614+ if ( count ( $ parent_column_unit ) <= 1 ) {
615+ $ parent_column_unit = 'rem ' ;
616+ $ parent_column_value = 12 ;
617+ } else {
618+ $ parent_column_unit = $ parent_column_unit [1 ];
619+
620+ if ( ! in_array ( $ parent_column_unit , array ( 'px ' , 'rem ' , 'em ' ), true ) ) {
621+ $ parent_column_unit = 'rem ' ;
622+ }
623+ }
624+
625+ /*
626+ * A default gap value is used for this computation because custom gap values may not be
627+ * viable to use in the computation of the container query value.
628+ */
629+ $ default_gap_value = 'px ' === $ parent_column_unit ? 24 : 1.5 ;
630+ $ container_query_value = $ column_span_number * $ parent_column_value + ( $ column_span_number - 1 ) * $ default_gap_value ;
631+ $ container_query_value = $ container_query_value . $ parent_column_unit ;
570632
571- if ( 'fixed ' === $ layout_from_parent && isset ( $ block ['attrs ' ]['style ' ]['layout ' ]['flexSize ' ] ) ) {
572- $ child_layout_styles [] = array (
573- 'selector ' => ". $ container_content_class " ,
574- 'declarations ' => array (
575- 'flex-basis ' => $ block ['attrs ' ]['style ' ]['layout ' ]['flexSize ' ],
576- 'box-sizing ' => 'border-box ' ,
577- ),
578- );
579- } elseif ( 'fill ' === $ layout_from_parent ) {
580633 $ child_layout_styles [] = array (
634+ 'rules_group ' => "@container (max-width: $ container_query_value ) " ,
581635 'selector ' => ". $ container_content_class " ,
582636 'declarations ' => array (
583- 'flex-grow ' => '1 ' ,
637+ 'grid-column ' => '1/- 1 ' ,
584638 ),
585639 );
586640 }
587641
588- wp_style_engine_get_stylesheet_from_css_rules (
642+ /*
643+ * Add to the style engine store to enqueue and render layout styles.
644+ * Return styles here just to check if any exist.
645+ */
646+ $ child_css = wp_style_engine_get_stylesheet_from_css_rules (
589647 $ child_layout_styles ,
590648 array (
591649 'context ' => 'block-supports ' ,
592650 'prettify ' => false ,
593651 )
594652 );
595653
596- $ outer_class_names [] = $ container_content_class ;
654+ if ( $ child_css ) {
655+ $ outer_class_names [] = $ container_content_class ;
656+ }
597657 }
598658
599659 // Prep the processor for modifying the block output.
@@ -851,6 +911,27 @@ function wp_render_layout_support_flag( $block_content, $block ) {
851911 return $ processor ->get_updated_html ();
852912}
853913
914+ /**
915+ * Check if the parent block exists and if it has a layout attribute.
916+ * If it does, add the parent layout to the parsed block
917+ *
918+ * @since 6.6.0
919+ * @access private
920+ *
921+ * @param array $parsed_block The parsed block.
922+ * @param array $source_block The source block.
923+ * @param WP_Block $parent_block The parent block.
924+ * @return array The parsed block with parent layout attribute if it exists.
925+ */
926+ function wp_add_parent_layout_to_parsed_block ( $ parsed_block , $ source_block , $ parent_block ) {
927+ if ( $ parent_block && isset ( $ parent_block ->parsed_block ['attrs ' ]['layout ' ] ) ) {
928+ $ parsed_block ['parentLayout ' ] = $ parent_block ->parsed_block ['attrs ' ]['layout ' ];
929+ }
930+ return $ parsed_block ;
931+ }
932+
933+ add_filter ( 'render_block_data ' , 'wp_add_parent_layout_to_parsed_block ' , 10 , 3 );
934+
854935// Register the block support.
855936WP_Block_Supports::get_instance ()->register (
856937 'layout ' ,
0 commit comments