diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php
index fcf9191dc32775..5869d521b2d380 100644
--- a/lib/block-supports/duotone.php
+++ b/lib/block-supports/duotone.php
@@ -351,7 +351,15 @@ function ( $selector ) use ( $duotone_id ) {
1
);
- return $content . $duotone;
+ add_action(
+ // Ideally we should use wp_head, but SVG defs can't be put in there.
+ 'wp_footer',
+ function () use ( $duotone ) {
+ echo $duotone;
+ }
+ );
+
+ return $content;
}
// Register the block support.
diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index 6d09ffa6d4e751..9048ca6183bd10 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -86,7 +86,17 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
1
);
- return $content . '';
+ // Ideally styles should be loaded in the head, but blocks may be parsed
+ // after that, so loading in the footer for now.
+ // See https://core.trac.wordpress.org/ticket/53494.
+ add_action(
+ 'wp_footer',
+ function () use ( $style ) {
+ echo '';
+ }
+ );
+
+ return $content;
}
// This can be removed when plugin support requires WordPress 5.8.0+.
diff --git a/packages/block-editor/src/components/block-list/head.js b/packages/block-editor/src/components/block-list/head.js
new file mode 100644
index 00000000000000..9f1ce763203524
--- /dev/null
+++ b/packages/block-editor/src/components/block-list/head.js
@@ -0,0 +1,18 @@
+/**
+ * WordPress dependencies
+ */
+import { createContext, useState } from '@wordpress/element';
+
+const context = createContext();
+
+export function Head( { children } ) {
+ const [ element, setElement ] = useState();
+ return (
+
+
+ { children }
+
+ );
+}
+
+Head.context = context;
diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js
index 46e5d56f9f0317..d393c31c8d41a0 100644
--- a/packages/block-editor/src/components/block-list/index.js
+++ b/packages/block-editor/src/components/block-list/index.js
@@ -22,6 +22,7 @@ import { usePreParsePatterns } from '../../utils/pre-parse-patterns';
import { LayoutProvider, defaultLayout } from './layout';
import BlockToolsBackCompat from '../block-tools/back-compat';
import { useBlockSelectionClearer } from '../block-selection-clearer';
+import { Head } from './head';
export const IntersectionObserver = createContext();
@@ -42,24 +43,26 @@ function Root( { className, children } ) {
[]
);
return (
-
- { children }
-
+
+
+ { children }
+
+
);
}
diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js
index c0de112b020d8d..46748fb04f3e6c 100644
--- a/packages/block-editor/src/hooks/duotone.js
+++ b/packages/block-editor/src/hooks/duotone.js
@@ -11,6 +11,7 @@ import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks';
import { SVG } from '@wordpress/components';
import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
import { addFilter } from '@wordpress/hooks';
+import { useContext, createPortal } from '@wordpress/element';
/**
* Internal dependencies
@@ -20,6 +21,7 @@ import {
__experimentalDuotoneControl as DuotoneControl,
useSetting,
} from '../components';
+import { Head } from '../components/block-list/head';
const EMPTY_ARRAY = [];
@@ -240,13 +242,19 @@ const withDuotoneStyles = createHigherOrderComponent(
const className = classnames( props?.className, id );
+ const element = useContext( Head.context );
+
return (
<>
-
+ { element &&
+ createPortal(
+ ,
+ element
+ ) }
>
);
diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js
index 2651521bd4574a..01f9c0b18c1cb5 100644
--- a/packages/block-editor/src/hooks/layout.js
+++ b/packages/block-editor/src/hooks/layout.js
@@ -20,6 +20,7 @@ import {
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { Icon, positionCenter, stretchWide } from '@wordpress/icons';
+import { useContext, createPortal } from '@wordpress/element';
/**
* Internal dependencies
@@ -28,6 +29,7 @@ import { store as blockEditorStore } from '../store';
import { InspectorControls } from '../components';
import useSetting from '../components/use-setting';
import { LayoutStyle } from '../components/block-list/layout';
+import { Head } from '../components/block-list/head';
function LayoutPanel( { setAttributes, attributes } ) {
const { layout = {} } = attributes;
@@ -210,12 +212,18 @@ export const withLayoutStyles = createHigherOrderComponent(
`wp-container-${ id }`
);
+ const element = useContext( Head.context );
+
return (
<>
-
+ { element &&
+ createPortal(
+ ,
+ element
+ ) }
>
);