diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index 30b5d8d02084a8..b53a90cde21855 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -581,28 +581,46 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
$child_layout_declarations['flex-grow'] = '1';
}
- if ( isset( $block['attrs']['style']['layout']['columnSpan'] ) ) {
- $column_span = $block['attrs']['style']['layout']['columnSpan'];
+ $column_start = isset( $block['attrs']['style']['layout']['columnStart'] ) ? $block['attrs']['style']['layout']['columnStart'] : null;
+ $column_span = isset( $block['attrs']['style']['layout']['columnSpan'] ) ? $block['attrs']['style']['layout']['columnSpan'] : null;
+ if ( $column_start && $column_span ) {
+ $child_layout_declarations['grid-column'] = "$column_start / span $column_span";
+ } elseif ( $column_start ) {
+ $child_layout_declarations['grid-column'] = "$column_start";
+ } elseif ( $column_span ) {
$child_layout_declarations['grid-column'] = "span $column_span";
}
- if ( isset( $block['attrs']['style']['layout']['rowSpan'] ) ) {
- $row_span = $block['attrs']['style']['layout']['rowSpan'];
+
+ $row_start = isset( $block['attrs']['style']['layout']['rowStart'] ) ? $block['attrs']['style']['layout']['rowStart'] : null;
+ $row_span = isset( $block['attrs']['style']['layout']['rowSpan'] ) ? $block['attrs']['style']['layout']['rowSpan'] : null;
+ if ( $row_start && $row_span ) {
+ $child_layout_declarations['grid-row'] = "$row_start / span $row_span";
+ } elseif ( $row_start ) {
+ $child_layout_declarations['grid-row'] = "$row_start";
+ } elseif ( $row_span ) {
$child_layout_declarations['grid-row'] = "span $row_span";
}
+
$child_layout_styles[] = array(
'selector' => ".$container_content_class",
'declarations' => $child_layout_declarations,
);
+ $minimum_column_width = isset( $block['attrs']['style']['layout']['minimumColumnWidth'] ) ? $block['attrs']['style']['layout']['minimumColumnWidth'] : null;
+ $column_count = isset( $block['attrs']['style']['layout']['columnCount'] ) ? $block['attrs']['style']['layout']['columnCount'] : null;
+
/*
- * If columnSpan is set, and the parent grid is responsive, i.e. if it has a minimumColumnWidth set,
- * the columnSpan should be removed on small grids. If there's a minimumColumnWidth, the grid is responsive.
- * But if the minimumColumnWidth value wasn't changed, it won't be set. In that case, if columnCount doesn't
- * exist, we can assume that the grid is responsive.
+ * If columnSpan or columnStart is set, and the parent grid is responsive, i.e. if it has a minimumColumnWidth set,
+ * the columnSpan should be removed once the grid is smaller than the span, and columnStart should be removed
+ * once the grid has less columns than the start.
+ * If there's a minimumColumnWidth, the grid is responsive. But if the minimumColumnWidth value wasn't changed, it won't be set.
+ * In that case, if columnCount doesn't exist, we can assume that the grid is responsive.
*/
- if ( isset( $block['attrs']['style']['layout']['columnSpan'] ) && ( isset( $block['parentLayout']['minimumColumnWidth'] ) || ! isset( $block['parentLayout']['columnCount'] ) ) ) {
- $column_span_number = floatval( $block['attrs']['style']['layout']['columnSpan'] );
- $parent_column_width = isset( $block['parentLayout']['minimumColumnWidth'] ) ? $block['parentLayout']['minimumColumnWidth'] : '12rem';
+ if ( ( $column_span || $column_start ) && ( $minimum_column_width || ! $column_count ) ) {
+ $column_span_number = floatval( $column_span );
+ $column_start_number = floatval( $column_start );
+ $highest_number = max( $column_span_number, $column_start_number );
+ $parent_column_width = $minimum_column_width ? $minimum_column_width : '12rem';
$parent_column_value = floatval( $parent_column_width );
$parent_column_unit = explode( $parent_column_value, $parent_column_width );
@@ -627,14 +645,16 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
* viable to use in the computation of the container query value.
*/
$default_gap_value = 'px' === $parent_column_unit ? 24 : 1.5;
- $container_query_value = $column_span_number * $parent_column_value + ( $column_span_number - 1 ) * $default_gap_value;
+ $container_query_value = $highest_number * $parent_column_value + ( $highest_number - 1 ) * $default_gap_value;
$container_query_value = $container_query_value . $parent_column_unit;
+ // If a span is set we want to preserve it as long as possible, otherwise we just reset the value.
+ $grid_column_value = $column_span ? '1/-1' : 'auto';
$child_layout_styles[] = array(
'rules_group' => "@container (max-width: $container_query_value )",
'selector' => ".$container_content_class",
'declarations' => array(
- 'grid-column' => '1/-1',
+ 'grid-column' => $grid_column_value,
),
);
}
diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js
index fcdbc4369f33e9..e0af72c238ad53 100644
--- a/packages/block-editor/src/components/child-layout-control/index.js
+++ b/packages/block-editor/src/components/child-layout-control/index.js
@@ -7,6 +7,10 @@ import {
__experimentalUnitControl as UnitControl,
__experimentalInputControl as InputControl,
__experimentalHStack as HStack,
+ __experimentalVStack as VStack,
+ __experimentalToolsPanelItem as ToolsPanelItem,
+ Flex,
+ FlexItem,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useEffect } from '@wordpress/element';
@@ -28,25 +32,62 @@ function helpText( selfStretch, parentLayout ) {
/**
* Form to edit the child layout value.
*
- * @param {Object} props Props.
- * @param {Object} props.value The child layout value.
- * @param {Function} props.onChange Function to update the child layout value.
- * @param {Object} props.parentLayout The parent layout value.
+ * @param {Object} props Props.
+ * @param {Object} props.value The child layout value.
+ * @param {Function} props.onChange Function to update the child layout value.
+ * @param {Object} props.parentLayout The parent layout value.
*
+ * @param {boolean} props.isShownByDefault
+ * @param {string} props.panelId
* @return {Element} child layout edit element.
*/
export default function ChildLayoutControl( {
value: childLayout = {},
onChange,
parentLayout,
+ isShownByDefault,
+ panelId,
} ) {
- const { selfStretch, flexSize, columnSpan, rowSpan } = childLayout;
+ const {
+ selfStretch,
+ flexSize,
+ columnStart,
+ rowStart,
+ columnSpan,
+ rowSpan,
+ } = childLayout;
const {
type: parentType,
default: { type: defaultParentType = 'default' } = {},
+ orientation = 'horizontal',
} = parentLayout ?? {};
const parentLayoutType = parentType || defaultParentType;
+ const hasFlexValue = () => !! selfStretch;
+ const flexResetLabel =
+ orientation === 'horizontal' ? __( 'Width' ) : __( 'Height' );
+ const resetFlex = () => {
+ onChange( {
+ selfStretch: undefined,
+ flexSize: undefined,
+ } );
+ };
+
+ const hasStartValue = () => !! columnStart || !! rowStart;
+ const hasSpanValue = () => !! columnSpan || !! rowSpan;
+ const resetGridStarts = () => {
+ onChange( {
+ columnStart: undefined,
+ rowStart: undefined,
+ } );
+ };
+ const resetGridSpans = () => {
+ onChange( {
+ columnSpan: undefined,
+ rowSpan: undefined,
+ } );
+ };
+
useEffect( () => {
if ( selfStretch === 'fixed' && ! flexSize ) {
onChange( {
@@ -59,7 +100,15 @@ export default function ChildLayoutControl( {
return (
<>
{ parentLayoutType === 'flex' && (
- <>
+
) }
- >
+
) }
{ parentLayoutType === 'grid' && (
-
- {
- onChange( {
- rowSpan,
- columnSpan: value,
- } );
- } }
- value={ columnSpan }
- min={ 1 }
- />
- {
- onChange( {
- columnSpan,
- rowSpan: value,
- } );
- } }
- value={ rowSpan }
- min={ 1 }
- />
-
+ <>
+
+ {
+ onChange( {
+ columnStart,
+ rowStart,
+ rowSpan,
+ columnSpan: value,
+ } );
+ } }
+ value={ columnSpan }
+ min={ 1 }
+ />
+ {
+ onChange( {
+ columnStart,
+ rowStart,
+ columnSpan,
+ rowSpan: value,
+ } );
+ } }
+ value={ rowSpan }
+ min={ 1 }
+ />
+
+ { window.__experimentalEnableGridInteractivity && (
+ // Use Flex with an explicit width on the FlexItem instead of HStack to
+ // work around an issue in webkit where inputs with a max attribute are
+ // sized incorrectly.
+
+
+ {
+ onChange( {
+ columnStart: value,
+ rowStart,
+ columnSpan,
+ rowSpan,
+ } );
+ } }
+ value={ columnStart }
+ min={ 1 }
+ max={ parentLayout?.columnCount }
+ />
+
+
+ {
+ onChange( {
+ columnStart,
+ rowStart: value,
+ columnSpan,
+ rowSpan,
+ } );
+ } }
+ value={ rowStart }
+ min={ 1 }
+ max={ parentLayout?.columnCount }
+ />
+
+
+ ) }
+ >
) }
>
);
diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js
index 1386df0dfe2894..94e53eec163721 100644
--- a/packages/block-editor/src/components/global-styles/dimensions-panel.js
+++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js
@@ -12,7 +12,6 @@ import {
__experimentalToolsPanelItem as ToolsPanelItem,
__experimentalBoxControl as BoxControl,
__experimentalHStack as HStack,
- __experimentalVStack as VStack,
__experimentalUnitControl as UnitControl,
__experimentalUseCustomUnits as useCustomUnits,
__experimentalView as View,
@@ -396,16 +395,7 @@ export default function DimensionsPanel( {
// Child Layout
const showChildLayoutControl = useHasChildLayout( settings );
const childLayout = inheritedValue?.layout;
- const { orientation = 'horizontal' } = settings?.parentLayout ?? {};
- const {
- type: parentType,
- default: { type: defaultParentType = 'default' } = {},
- } = settings?.parentLayout ?? {};
- const parentLayoutType = parentType || defaultParentType;
- const flexResetLabel =
- orientation === 'horizontal' ? __( 'Width' ) : __( 'Height' );
- const childLayoutResetLabel =
- parentLayoutType === 'flex' ? flexResetLabel : __( 'Grid spans' );
+
const setChildLayout = ( newChildLayout ) => {
onChange( {
...value,
@@ -414,15 +404,6 @@ export default function DimensionsPanel( {
},
} );
};
- const resetChildLayoutValue = () => {
- setChildLayout( {
- selfStretch: undefined,
- flexSize: undefined,
- columnSpan: undefined,
- rowSpan: undefined,
- } );
- };
- const hasChildLayoutValue = () => !! value?.layout;
const resetAllFilter = useCallback( ( previousValue ) => {
return {
@@ -433,6 +414,8 @@ export default function DimensionsPanel( {
wideSize: undefined,
selfStretch: undefined,
flexSize: undefined,
+ columnStart: undefined,
+ rowStart: undefined,
columnSpan: undefined,
rowSpan: undefined,
} ),
@@ -650,24 +633,16 @@ export default function DimensionsPanel( {
) }
{ showChildLayoutControl && (
-
-
-
+ />
) }
{ showMinHeightControl && (