diff --git a/packages/edit-site/src/components/global-styles/screen-layout.js b/packages/edit-site/src/components/global-styles/screen-layout.js
index 61c64b88f0e480..1e68309fe01866 100644
--- a/packages/edit-site/src/components/global-styles/screen-layout.js
+++ b/packages/edit-site/src/components/global-styles/screen-layout.js
@@ -23,7 +23,11 @@ function ScreenLayout() {
const [ rawSettings ] = useGlobalSetting( '' );
const settings = useSettingsForBlockElement( rawSettings );
const hasDimensionsPanel = useHasDimensionsPanel( settings );
- const hasBackgroundPanel = useHasBackgroundPanel( settings );
+ /*
+ * Use the raw settings to determine if the background panel should be displayed,
+ * as the background panel is not dependent on the block element settings.
+ */
+ const hasBackgroundPanel = useHasBackgroundPanel( rawSettings );
return (
<>
diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js
index 2917c6905e3f0d..823cf852d14814 100644
--- a/packages/editor/src/components/provider/use-block-editor-settings.js
+++ b/packages/editor/src/components/provider/use-block-editor-settings.js
@@ -27,7 +27,7 @@ import { lock, unlock } from '../../lock-unlock';
import { useGlobalStylesContext } from '../global-styles-provider';
const EMPTY_BLOCKS_LIST = [];
-const DEFAULT_STYLES = {};
+const EMPTY_OBJECT = {};
function __experimentalReusableBlocksSelect( select ) {
return (
@@ -88,8 +88,12 @@ const BLOCK_EDITOR_SETTINGS = [
'__experimentalArchiveTitleNameLabel',
];
-const { globalStylesDataKey, selectBlockPatternsKey, reusableBlocksSelectKey } =
- unlock( privateApis );
+const {
+ globalStylesDataKey,
+ globalStylesLinksDataKey,
+ selectBlockPatternsKey,
+ reusableBlocksSelectKey,
+} = unlock( privateApis );
/**
* React hook used to compute the block editor settings to use for the post editor.
@@ -179,7 +183,8 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) {
);
const { merged: mergedGlobalStyles } = useGlobalStylesContext();
- const globalStylesData = mergedGlobalStyles.styles ?? DEFAULT_STYLES;
+ const globalStylesData = mergedGlobalStyles.styles ?? EMPTY_OBJECT;
+ const globalStylesLinksData = mergedGlobalStyles._links ?? EMPTY_OBJECT;
const settingsBlockPatterns =
settings.__experimentalAdditionalBlockPatterns ?? // WP 6.0
@@ -268,6 +273,7 @@ function useBlockEditorSettings( settings, postType, postId, renderingMode ) {
)
),
[ globalStylesDataKey ]: globalStylesData,
+ [ globalStylesLinksDataKey ]: globalStylesLinksData,
allowedBlockTypes,
allowRightClickOverrides,
focusMode: focusMode && ! forceDisableFocusMode,
diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php
index e7a1b44049393e..d2339f2496290c 100644
--- a/phpunit/class-wp-theme-json-resolver-test.php
+++ b/phpunit/class-wp-theme-json-resolver-test.php
@@ -1216,6 +1216,22 @@ public function test_resolve_theme_file_uris() {
'url' => 'file:./example/img/image.png',
),
),
+ 'blocks' => array(
+ 'core/quote' => array(
+ 'background' => array(
+ 'backgroundImage' => array(
+ 'url' => 'file:./example/img/quote.png',
+ ),
+ ),
+ ),
+ 'core/verse' => array(
+ 'background' => array(
+ 'backgroundImage' => array(
+ 'url' => 'file:./example/img/verse.png',
+ ),
+ ),
+ ),
+ ),
),
)
);
@@ -1228,6 +1244,22 @@ public function test_resolve_theme_file_uris() {
'url' => 'https://example.org/wp-content/themes/example-theme/example/img/image.png',
),
),
+ 'blocks' => array(
+ 'core/quote' => array(
+ 'background' => array(
+ 'backgroundImage' => array(
+ 'url' => 'https://example.org/wp-content/themes/example-theme/example/img/quote.png',
+ ),
+ ),
+ ),
+ 'core/verse' => array(
+ 'background' => array(
+ 'backgroundImage' => array(
+ 'url' => 'https://example.org/wp-content/themes/example-theme/example/img/verse.png',
+ ),
+ ),
+ ),
+ ),
),
);
@@ -1261,6 +1293,22 @@ public function test_get_resolved_theme_uris() {
'url' => 'file:./example/img/image.png',
),
),
+ 'blocks' => array(
+ 'core/quote' => array(
+ 'background' => array(
+ 'backgroundImage' => array(
+ 'url' => 'file:./example/img/quote.jpg',
+ ),
+ ),
+ ),
+ 'core/verse' => array(
+ 'background' => array(
+ 'backgroundImage' => array(
+ 'url' => 'file:./example/img/verse.gif',
+ ),
+ ),
+ ),
+ ),
),
)
);
@@ -1272,6 +1320,18 @@ public function test_get_resolved_theme_uris() {
'target' => 'styles.background.backgroundImage.url',
'type' => 'image/png',
),
+ array(
+ 'name' => 'file:./example/img/quote.jpg',
+ 'href' => 'https://example.org/wp-content/themes/example-theme/example/img/quote.jpg',
+ 'target' => 'styles.blocks.core/quote.background.backgroundImage.url',
+ 'type' => 'image/jpeg',
+ ),
+ array(
+ 'name' => 'file:./example/img/verse.gif',
+ 'href' => 'https://example.org/wp-content/themes/example-theme/example/img/verse.gif',
+ 'target' => 'styles.blocks.core/verse.background.backgroundImage.url',
+ 'type' => 'image/gif',
+ ),
);
/*
diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php
index b188ce4fce6abc..2d6d4dbb668c94 100644
--- a/phpunit/class-wp-theme-json-test.php
+++ b/phpunit/class-wp-theme-json-test.php
@@ -4782,7 +4782,7 @@ public function test_get_top_level_background_image_styles() {
);
$expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}";
- $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background styles type does not match expectations' );
+ $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background styles do not match expectations' );
$theme_json = new WP_Theme_JSON_Gutenberg(
array(
@@ -4799,7 +4799,61 @@ public function test_get_top_level_background_image_styles() {
);
$expected_styles = "html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:root :where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}";
- $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background image as string type does not match expectations' );
+ $this->assertSame( $expected_styles, $theme_json->get_styles_for_block( $body_node ), 'Styles returned from "::get_styles_for_block()" with top-level background image as string type do not match expectations' );
+ }
+
+ public function test_get_block_background_image_styles() {
+ $theme_json = new WP_Theme_JSON_Gutenberg(
+ array(
+ 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
+ 'styles' => array(
+ 'blocks' => array(
+ 'core/group' => array(
+ 'background' => array(
+ 'backgroundImage' => "url('http://example.org/group.png')",
+ 'backgroundSize' => 'cover',
+ 'backgroundRepeat' => 'no-repeat',
+ 'backgroundPosition' => 'center center',
+ ),
+ ),
+ 'core/quote' => array(
+ 'background' => array(
+ 'backgroundImage' => array(
+ 'url' => 'http://example.org/quote.png',
+ ),
+ 'backgroundSize' => 'cover',
+ 'backgroundRepeat' => 'no-repeat',
+ 'backgroundPosition' => 'center center',
+ ),
+ ),
+ ),
+ ),
+ )
+ );
+
+ $quote_node = array(
+ 'name' => 'core/quote',
+ 'path' => array( 'styles', 'blocks', 'core/quote' ),
+ 'selector' => '.wp-block-quote',
+ 'selectors' => array(
+ 'root' => '.wp-block-quote',
+ ),
+ );
+
+ $quote_styles = ":root :where(.wp-block-quote){background-image: url('http://example.org/quote.png');background-position: center center;background-repeat: no-repeat;background-size: cover;}";
+ $this->assertSame( $quote_styles, $theme_json->get_styles_for_block( $quote_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles do not match expectations' );
+
+ $group_node = array(
+ 'name' => 'core/group',
+ 'path' => array( 'styles', 'blocks', 'core/group' ),
+ 'selector' => '.wp-block-group',
+ 'selectors' => array(
+ 'root' => '.wp-block-group',
+ ),
+ );
+
+ $group_styles = ":root :where(.wp-block-group){background-image: url('http://example.org/group.png');background-position: center center;background-repeat: no-repeat;background-size: cover;}";
+ $this->assertSame( $group_styles, $theme_json->get_styles_for_block( $group_node ), 'Styles returned from "::get_styles_for_block()" with block-level background styles as string type do not match expectations' );
}
/**
diff --git a/schemas/json/theme.json b/schemas/json/theme.json
index ec42bd1d54f0b7..f1666253e3de3e 100644
--- a/schemas/json/theme.json
+++ b/schemas/json/theme.json
@@ -1162,6 +1162,68 @@
"stylesProperties": {
"type": "object",
"properties": {
+ "background": {
+ "description": "Background styles.",
+ "type": "object",
+ "properties": {
+ "backgroundImage": {
+ "description": "Sets the `background-image` CSS property.",
+ "oneOf": [
+ {
+ "description": "A valid CSS value for the background-image CSS property.",
+ "type": "string"
+ },
+ {
+ "type": "object",
+ "properties": {
+ "url": {
+ "description": "A URL to an image file, or a path to a file relative to the theme root directory, and prefixed with `file:`, e.g., 'file:./path/to/file.png'.",
+ "type": "string"
+ }
+ },
+ "additionalProperties": false
+ },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ },
+ "backgroundPosition": {
+ "description": "Sets the `background-position` CSS property.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ },
+ "backgroundRepeat": {
+ "description": "Sets the `background-repeat` CSS property.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ },
+ "backgroundSize": {
+ "description": "Sets the `background-size` CSS property.",
+ "oneOf": [
+ {
+ "type": "string"
+ },
+ {
+ "$ref": "#/definitions/refComplete"
+ }
+ ]
+ }
+ },
+ "additionalProperties": false
+ },
"border": {
"description": "Border styles.",
"type": "object",
@@ -1814,6 +1876,7 @@
},
{
"properties": {
+ "background": {},
"border": {},
"color": {},
"dimensions": {},
@@ -1840,6 +1903,7 @@
{
"properties": {
"border": {},
+ "background": {},
"color": {},
"filter": {},
"shadow": {},
@@ -2248,6 +2312,7 @@
},
{
"properties": {
+ "background": {},
"border": {},
"color": {},
"dimensions": {},
@@ -2743,6 +2808,7 @@
},
{
"properties": {
+ "background": {},
"border": {},
"color": {},
"spacing": {},
@@ -2759,68 +2825,6 @@
"description": "Styles defined on a per-block basis using the block's selector.",
"$ref": "#/definitions/stylesBlocksPropertiesComplete"
},
- "background": {
- "description": "Background styles.",
- "type": "object",
- "properties": {
- "backgroundImage": {
- "description": "Sets the `background-image` CSS property.",
- "oneOf": [
- {
- "description": "A valid CSS value for the background-image property, or a path to a file relative to the theme root directory, and prefixed with `file:`, e.g., 'file:./path/to/file.png'.",
- "type": "string"
- },
- {
- "type": "object",
- "properties": {
- "url": {
- "description": "A URL to an image file.",
- "type": "string"
- }
- },
- "additionalProperties": false
- },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- },
- "backgroundPosition": {
- "description": "Sets the `background-position` CSS property.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- },
- "backgroundRepeat": {
- "description": "Sets the `background-repeat` CSS property.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- },
- "backgroundSize": {
- "description": "Sets the `background-size` CSS property.",
- "oneOf": [
- {
- "type": "string"
- },
- {
- "$ref": "#/definitions/refComplete"
- }
- ]
- }
- },
- "additionalProperties": false
- },
"variations": {
"$ref": "#/definitions/stylesVariationsProperties"
}