diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index 15a7a131f8a9b..b61311362893a 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -291,6 +291,23 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
return '';
}
+/**
+ * Gets classname from last tag in a string of HTML.
+ *
+ * @param string $html markup to be processed.
+ * @return string String of inner wrapper classnames.
+ */
+function gutenberg_get_classnames_from_last_tag( $html ) {
+ $tags = new WP_HTML_Tag_Processor( $html );
+ $last_classnames = '';
+
+ while ( $tags->next_tag() ) {
+ $last_classnames = $tags->get_attribute( 'class' );
+ }
+
+ return $last_classnames;
+}
+
/**
* Renders the layout config to the block wrapper.
*
@@ -320,7 +337,6 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
$class_names = array();
$layout_definitions = _wp_array_get( $global_layout_settings, array( 'definitions' ), array() );
- $block_classname = wp_get_block_default_classname( $block['blockName'] );
$container_class = wp_unique_id( 'wp-container-' );
$layout_classname = '';
@@ -397,7 +413,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
$should_skip_gap_serialization = gutenberg_should_skip_block_supports_serialization( $block_type, 'spacing', 'blockGap' );
$style = gutenberg_get_layout_style(
- ".$block_classname.$container_class",
+ ".$container_class.$container_class",
$used_layout,
$has_block_gap_support,
$gap_value,
@@ -412,16 +428,22 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
}
}
- /*
- * This assumes the hook only applies to blocks with a single wrapper.
- * A limitation of this hook is that nested inner blocks wrappers are not yet supported.
- */
- $content = preg_replace(
- '/' . preg_quote( 'class="', '/' ) . '/',
- 'class="' . esc_attr( implode( ' ', $class_names ) ) . ' ',
- $block_content,
- 1
- );
+ /**
+ * The first chunk of innerContent contains the block markup up until the inner blocks start.
+ * We want to target the opening tag of the inner blocks wrapper, which is the last tag in that chunk.
+ */
+ $inner_content_classnames = isset( $block['innerContent'][0] ) && 'string' === gettype( $block['innerContent'][0] ) ? gutenberg_get_classnames_from_last_tag( $block['innerContent'][0] ) : '';
+
+ $content = new WP_HTML_Tag_Processor( $block_content );
+ if ( $inner_content_classnames ) {
+ $content->next_tag( array( 'class_name' => $inner_content_classnames ) );
+ foreach ( $class_names as $class_name ) {
+ $content->add_class( $class_name );
+ }
+ } else {
+ $content->next_tag();
+ $content->add_class( implode( ' ', $class_names ) );
+ }
return $content;
}
@@ -433,6 +455,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
'register_attribute' => 'gutenberg_register_layout_support',
)
);
+
if ( function_exists( 'wp_render_layout_support_flag' ) ) {
remove_filter( 'render_block', 'wp_render_layout_support_flag' );
}
diff --git a/packages/block-editor/src/components/block-edit/index.js b/packages/block-editor/src/components/block-edit/index.js
index 9b2875b3018a3..747e25b820847 100644
--- a/packages/block-editor/src/components/block-edit/index.js
+++ b/packages/block-editor/src/components/block-edit/index.js
@@ -20,11 +20,12 @@ import { BlockEditContextProvider, useBlockEditContext } from './context';
export { useBlockEditContext };
export default function BlockEdit( props ) {
- const { name, isSelected, clientId } = props;
+ const { name, isSelected, clientId, __unstableLayoutClassNames } = props;
const context = {
name,
isSelected,
clientId,
+ __unstableLayoutClassNames,
};
return (
);
diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js
index 4105d7291957e..8afc6482eb33f 100644
--- a/packages/block-editor/src/components/inner-blocks/index.js
+++ b/packages/block-editor/src/components/inner-blocks/index.js
@@ -150,7 +150,9 @@ const ForwardedInnerBlocks = forwardRef( ( props, ref ) => {
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/inner-blocks/README.md
*/
export function useInnerBlocksProps( props = {}, options = {} ) {
- const { clientId } = useBlockEditContext();
+ const { __unstableDisableLayoutClassNames } = options;
+ const { clientId, __unstableLayoutClassNames: layoutClassNames = '' } =
+ useBlockEditContext();
const isSmallScreen = useViewportMatch( 'medium', '<' );
const { __experimentalCaptureToolbars, hasOverlay } = useSelect(
( select ) => {
@@ -200,12 +202,14 @@ export function useInnerBlocksProps( props = {}, options = {} ) {
innerBlocksProps.value && innerBlocksProps.onChange
? ControlledInnerBlocks
: UncontrolledInnerBlocks;
+
return {
...props,
ref,
className: classnames(
props.className,
'block-editor-block-list__layout',
+ __unstableDisableLayoutClassNames ? '' : layoutClassNames,
{
'has-overlay': hasOverlay,
}
diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js
index 73d655c57c2ac..eeea8f3df2c8c 100644
--- a/packages/block-editor/src/hooks/layout.js
+++ b/packages/block-editor/src/hooks/layout.js
@@ -9,11 +9,7 @@ import { kebabCase } from 'lodash';
*/
import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
import { addFilter } from '@wordpress/hooks';
-import {
- getBlockDefaultClassName,
- getBlockSupport,
- hasBlockSupport,
-} from '@wordpress/blocks';
+import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks';
import { useSelect } from '@wordpress/data';
import {
Button,
@@ -366,9 +362,8 @@ export const withLayoutStyles = createHigherOrderComponent(
const layoutClasses = hasLayoutBlockSupport
? useLayoutClasses( block )
: null;
- const selector = `.${ getBlockDefaultClassName(
- name
- ) }.wp-container-${ id }`;
+ // Higher specificity to override defaults from theme.json.
+ const selector = `.wp-container-${ id }.wp-container-${ id }`;
const blockGapSupport = useSetting( 'spacing.blockGap' );
const hasBlockGapSupport = blockGapSupport !== null;
@@ -413,7 +408,10 @@ export const withLayoutStyles = createHigherOrderComponent(
/>,
element
) }
-
+
>
);
}
diff --git a/packages/block-library/src/gallery/gallery.js b/packages/block-library/src/gallery/gallery.js
index 9a551b6e0d9f7..e6176cc8a7256 100644
--- a/packages/block-library/src/gallery/gallery.js
+++ b/packages/block-library/src/gallery/gallery.js
@@ -26,6 +26,7 @@ export const Gallery = ( props ) => {
mediaPlaceholder,
insertBlocksAfter,
blockProps,
+ __unstableLayoutClassNames: layoutClassNames,
} = props;
const { align, columns, caption, imageCrop } = attributes;
@@ -42,6 +43,7 @@ export const Gallery = ( props ) => {
{ ...innerBlocksProps }
className={ classnames(
blockProps.className,
+ layoutClassNames,
'blocks-gallery-grid',
{
[ `align${ align }` ]: align,
diff --git a/packages/block-library/src/group/edit.js b/packages/block-library/src/group/edit.js
index 9d43c4339ba1f..efe0d0ede9ebc 100644
--- a/packages/block-library/src/group/edit.js
+++ b/packages/block-library/src/group/edit.js
@@ -35,7 +35,12 @@ const htmlElementMessages = {
),
};
-function GroupEdit( { attributes, setAttributes, clientId } ) {
+function GroupEdit( {
+ attributes,
+ setAttributes,
+ clientId,
+ __unstableLayoutClassNames: layoutClassNames,
+} ) {
const { hasInnerBlocks, themeSupportsLayout } = useSelect(
( select ) => {
const { getBlock, getSettings } = select( blockEditorStore );
@@ -55,7 +60,9 @@ function GroupEdit( { attributes, setAttributes, clientId } ) {
const { type = 'default' } = usedLayout;
const layoutSupportEnabled = themeSupportsLayout || type === 'flex';
- const blockProps = useBlockProps();
+ const blockProps = useBlockProps( {
+ className: ! layoutSupportEnabled ? layoutClassNames : null,
+ } );
const innerBlocksProps = useInnerBlocksProps(
layoutSupportEnabled
@@ -67,6 +74,7 @@ function GroupEdit( { attributes, setAttributes, clientId } ) {
? undefined
: InnerBlocks.ButtonBlockAppender,
__experimentalLayout: layoutSupportEnabled ? usedLayout : undefined,
+ __unstableDisableLayoutClassNames: ! layoutSupportEnabled,
}
);
diff --git a/packages/block-library/src/post-content/edit.js b/packages/block-library/src/post-content/edit.js
index 1949553b2540f..e190101aa0515 100644
--- a/packages/block-library/src/post-content/edit.js
+++ b/packages/block-library/src/post-content/edit.js
@@ -84,8 +84,8 @@ function Content( props ) {
);
}
-function Placeholder() {
- const blockProps = useBlockProps();
+function Placeholder( { layoutClassNames } ) {
+ const blockProps = useBlockProps( { className: layoutClassNames } );
return (
@@ -118,7 +118,11 @@ function RecursionError() {
);
}
-export default function PostContentEdit( { context, attributes } ) {
+export default function PostContentEdit( {
+ context,
+ attributes,
+ __unstableLayoutClassNames: layoutClassNames,
+} ) {
const { postId: contextPostId, postType: contextPostType } = context;
const { layout = {} } = attributes;
const hasAlreadyRendered = useHasRecursion( contextPostId );
@@ -132,7 +136,7 @@ export default function PostContentEdit( { context, attributes } ) {
{ contextPostId && contextPostType ? (
) : (
-
+
) }
);