diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index e239ed023bd62..e6e3663b82318 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -30,6 +30,7 @@ function gutenberg_register_layout_support( $block_type ) {
*
* @param string $selector CSS selector.
* @param array $layout Layout object. The one that is passed has already checked the existence of default block layout.
+ * @param array|null $padding Padding applied to the current block.
* @param boolean $has_block_gap_support Whether the theme has support for the block gap.
* @param string $gap_value The block gap value to apply.
* @param boolean $should_skip_gap_serialization Whether to skip applying the user-defined value set in the editor.
@@ -37,7 +38,7 @@ function gutenberg_register_layout_support( $block_type ) {
*
* @return string CSS style.
*/
-function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support = false, $gap_value = null, $should_skip_gap_serialization = false, $fallback_gap_value = '0.5em' ) {
+function gutenberg_get_layout_style( $selector, $layout, $padding, $has_block_gap_support = false, $gap_value = null, $should_skip_gap_serialization = false, $fallback_gap_value = '0.5em' ) {
$layout_type = isset( $layout['type'] ) ? $layout['type'] : 'default';
$style = '';
@@ -54,14 +55,37 @@ function gutenberg_get_layout_style( $selector, $layout, $has_block_gap_support
$wide_max_width_value = wp_strip_all_tags( explode( ';', $wide_max_width_value )[0] );
if ( $content_size || $wide_size ) {
- $style = "$selector > :where(:not(.alignleft):not(.alignright)) {";
+ // Add a .wp-container-default-layout so this only applies to lower level default layouts, not the top level
+ $style = ".wp-container-default-layout $selector {";
+ // Using important here to override the inline padding that could be potentially
+ // applied using the custom padding control before the layout inheritance is applied.
+ $style .= sprintf(
+ 'padding: %s %s %s %s !important',
+ isset( $padding['top'] ) ? $padding['top'] : 0,
+ isset( $padding['right'] ) ? $padding['right'] : 0,
+ isset( $padding['bottom'] ) ? $padding['bottom'] : 0,
+ isset( $padding['left'] ) ? $padding['left'] : 0
+ );
+ $style .= '}';
+ $style .= "$selector > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {";
$style .= 'max-width: ' . esc_html( $all_max_width_value ) . ';';
$style .= 'margin-left: auto !important;';
$style .= 'margin-right: auto !important;';
$style .= '}';
$style .= "$selector > .alignwide { max-width: " . esc_html( $wide_max_width_value ) . ';}';
- $style .= "$selector .alignfull { max-width: none; }";
+ // Add a .wp-container-default-layout so this only applies to lower level default layouts, not the top level// Add a .wp-container-default-layout so this only applies to lower level default layouts, not the top level.
+ $style .= ".wp-container-default-layout $selector > .alignfull {";
+ $style .= 'max-width: none;';
+ $style .= isset( $padding['left'] ) ? sprintf( 'margin-left: calc( -1 * %s ) !important;', $padding['left'] ) : '';
+ $style .= isset( $padding['right'] ) ? sprintf( 'margin-right: calc( -1 * %s ) !important;', $padding['right'] ) : '';
+ $style .= '}';
+
+ // Add padding to full wide blocks that inherit default layout, so the content doesn't touch the edges.
+ $style .= "$selector > .alignfull {";
+ $style .= isset( $padding['left'] ) ? sprintf( 'padding-left: %s !important;', $padding['left'] ) : '';
+ $style .= isset( $padding['right'] ) ? sprintf( 'padding-right: %s !important;', $padding['right'] ) : '';
+ $style .= '}';
}
$style .= "$selector > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }";
@@ -159,9 +183,12 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
if ( ! $support_layout ) {
return $block_content;
}
-
+ $class_name = wp_unique_id( 'wp-container-' );
+ $selector = '.' . $class_name;
$block_gap = gutenberg_get_global_settings( array( 'spacing', 'blockGap' ) );
$default_layout = gutenberg_get_global_settings( array( 'layout' ) );
+ $default_padding = gutenberg_get_global_styles( array( 'spacing', 'padding' ) );
+ $padding = _wp_array_get( $block, array( 'attrs', 'style', 'spacing', 'padding' ), null );
$has_block_gap_support = isset( $block_gap ) ? null !== $block_gap : false;
$default_block_layout = _wp_array_get( $block_type->supports, array( '__experimentalLayout', 'default' ), array() );
$used_layout = isset( $block['attrs']['layout'] ) ? $block['attrs']['layout'] : $default_block_layout;
@@ -169,12 +196,15 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
if ( ! $default_layout ) {
return $block_content;
}
- $used_layout = $default_layout;
+ $class_name .= ' wp-container-default-layout';
+ $selector .= '.wp-container-default-layout';
+ $used_layout = $default_layout;
+ //TODO - can we allow padding from the block settings?
+ $padding = isset( $default_padding ) ? $default_padding : null;
}
$class_names = array();
- $container_class = wp_unique_id( 'wp-container-' );
- $class_names[] = $container_class;
+ $class_names[] = $class_name;
// The following section was added to reintroduce a small set of layout classnames that were
// removed in the 5.9 release (https://github.com/WordPress/gutenberg/issues/38719). It is
@@ -193,6 +223,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
}
$gap_value = _wp_array_get( $block, array( 'attrs', 'style', 'spacing', 'blockGap' ) );
+
// Skip if gap value contains unsupported characters.
// Regex for CSS value borrowed from `safecss_filter_attr`, and used here
// because we only want to match against the value, not the CSS attribute.
@@ -209,7 +240,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) {
// If a block's block.json skips serialization for spacing or spacing.blockGap,
// don't apply the user-defined value to the styles.
$should_skip_gap_serialization = gutenberg_should_skip_block_supports_serialization( $block_type, 'spacing', 'blockGap' );
- $style = gutenberg_get_layout_style( ".$container_class", $used_layout, $has_block_gap_support, $gap_value, $should_skip_gap_serialization, $fallback_gap_value );
+ $style = gutenberg_get_layout_style( $selector, $used_layout, $padding, $has_block_gap_support, $gap_value, $should_skip_gap_serialization, $fallback_gap_value );
// This assumes the hook only applies to blocks with a single wrapper.
// I think this is a reasonable limitation for that particular hook.
$content = preg_replace(
diff --git a/lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php b/lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php
index 77d731b9d4544..73c204513faee 100644
--- a/lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php
+++ b/lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php
@@ -22,49 +22,54 @@ class WP_Theme_JSON_6_0 extends WP_Theme_JSON_5_9 {
* path to the value in theme.json & block attributes.
*/
const PROPERTIES_METADATA = array(
- 'background' => array( 'color', 'gradient' ),
- 'background-color' => array( 'color', 'background' ),
- 'border-radius' => array( 'border', 'radius' ),
- 'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ),
- 'border-top-right-radius' => array( 'border', 'radius', 'topRight' ),
- 'border-bottom-left-radius' => array( 'border', 'radius', 'bottomLeft' ),
- 'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ),
- 'border-color' => array( 'border', 'color' ),
- 'border-width' => array( 'border', 'width' ),
- 'border-style' => array( 'border', 'style' ),
- 'border-top-color' => array( 'border', 'top', 'color' ),
- 'border-top-width' => array( 'border', 'top', 'width' ),
- 'border-top-style' => array( 'border', 'top', 'style' ),
- 'border-right-color' => array( 'border', 'right', 'color' ),
- 'border-right-width' => array( 'border', 'right', 'width' ),
- 'border-right-style' => array( 'border', 'right', 'style' ),
- 'border-bottom-color' => array( 'border', 'bottom', 'color' ),
- 'border-bottom-width' => array( 'border', 'bottom', 'width' ),
- 'border-bottom-style' => array( 'border', 'bottom', 'style' ),
- 'border-left-color' => array( 'border', 'left', 'color' ),
- 'border-left-width' => array( 'border', 'left', 'width' ),
- 'border-left-style' => array( 'border', 'left', 'style' ),
- 'color' => array( 'color', 'text' ),
- 'font-family' => array( 'typography', 'fontFamily' ),
- 'font-size' => array( 'typography', 'fontSize' ),
- 'font-style' => array( 'typography', 'fontStyle' ),
- 'font-weight' => array( 'typography', 'fontWeight' ),
- 'letter-spacing' => array( 'typography', 'letterSpacing' ),
- 'line-height' => array( 'typography', 'lineHeight' ),
- 'margin' => array( 'spacing', 'margin' ),
- 'margin-top' => array( 'spacing', 'margin', 'top' ),
- 'margin-right' => array( 'spacing', 'margin', 'right' ),
- 'margin-bottom' => array( 'spacing', 'margin', 'bottom' ),
- 'margin-left' => array( 'spacing', 'margin', 'left' ),
- 'padding' => array( 'spacing', 'padding' ),
- 'padding-top' => array( 'spacing', 'padding', 'top' ),
- 'padding-right' => array( 'spacing', 'padding', 'right' ),
- 'padding-bottom' => array( 'spacing', 'padding', 'bottom' ),
- 'padding-left' => array( 'spacing', 'padding', 'left' ),
- '--wp--style--block-gap' => array( 'spacing', 'blockGap' ),
- 'text-decoration' => array( 'typography', 'textDecoration' ),
- 'text-transform' => array( 'typography', 'textTransform' ),
- 'filter' => array( 'filter', 'duotone' ),
+ 'background' => array( 'color', 'gradient' ),
+ 'background-color' => array( 'color', 'background' ),
+ 'border-radius' => array( 'border', 'radius' ),
+ 'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ),
+ 'border-top-right-radius' => array( 'border', 'radius', 'topRight' ),
+ 'border-bottom-left-radius' => array( 'border', 'radius', 'bottomLeft' ),
+ 'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ),
+ 'border-color' => array( 'border', 'color' ),
+ 'border-width' => array( 'border', 'width' ),
+ 'border-style' => array( 'border', 'style' ),
+ 'border-top-color' => array( 'border', 'top', 'color' ),
+ 'border-top-width' => array( 'border', 'top', 'width' ),
+ 'border-top-style' => array( 'border', 'top', 'style' ),
+ 'border-right-color' => array( 'border', 'right', 'color' ),
+ 'border-right-width' => array( 'border', 'right', 'width' ),
+ 'border-right-style' => array( 'border', 'right', 'style' ),
+ 'border-bottom-color' => array( 'border', 'bottom', 'color' ),
+ 'border-bottom-width' => array( 'border', 'bottom', 'width' ),
+ 'border-bottom-style' => array( 'border', 'bottom', 'style' ),
+ 'border-left-color' => array( 'border', 'left', 'color' ),
+ 'border-left-width' => array( 'border', 'left', 'width' ),
+ 'border-left-style' => array( 'border', 'left', 'style' ),
+ 'color' => array( 'color', 'text' ),
+ 'font-family' => array( 'typography', 'fontFamily' ),
+ 'font-size' => array( 'typography', 'fontSize' ),
+ 'font-style' => array( 'typography', 'fontStyle' ),
+ 'font-weight' => array( 'typography', 'fontWeight' ),
+ 'letter-spacing' => array( 'typography', 'letterSpacing' ),
+ 'line-height' => array( 'typography', 'lineHeight' ),
+ 'margin' => array( 'spacing', 'margin' ),
+ 'margin-top' => array( 'spacing', 'margin', 'top' ),
+ 'margin-right' => array( 'spacing', 'margin', 'right' ),
+ 'margin-bottom' => array( 'spacing', 'margin', 'bottom' ),
+ 'margin-left' => array( 'spacing', 'margin', 'left' ),
+ 'padding' => array( 'spacing', 'padding' ),
+ 'padding-top' => array( 'spacing', 'padding', 'top' ),
+ 'padding-right' => array( 'spacing', 'padding', 'right' ),
+ 'padding-bottom' => array( 'spacing', 'padding', 'bottom' ),
+ 'padding-left' => array( 'spacing', 'padding', 'left' ),
+ '--wp--style--root--padding' => array( 'spacing', 'padding' ),
+ '--wp--style--root--padding-top' => array( 'spacing', 'padding', 'top' ),
+ '--wp--style--root--padding-right' => array( 'spacing', 'padding', 'right' ),
+ '--wp--style--root--padding-bottom' => array( 'spacing', 'padding', 'bottom' ),
+ '--wp--style--root--padding-left' => array( 'spacing', 'padding', 'left' ),
+ '--wp--style--block-gap' => array( 'spacing', 'blockGap' ),
+ 'text-decoration' => array( 'typography', 'textDecoration' ),
+ 'text-transform' => array( 'typography', 'textTransform' ),
+ 'filter' => array( 'filter', 'duotone' ),
);
/**
@@ -202,14 +207,15 @@ class WP_Theme_JSON_6_0 extends WP_Theme_JSON_5_9 {
* @var array
*/
const VALID_SETTINGS = array(
- 'appearanceTools' => null,
- 'border' => array(
+ 'appearanceTools' => null,
+ 'useRootVariables' => null,
+ 'border' => array(
'color' => null,
'radius' => null,
'style' => null,
'width' => null,
),
- 'color' => array(
+ 'color' => array(
'background' => null,
'custom' => null,
'customDuotone' => null,
@@ -223,18 +229,19 @@ class WP_Theme_JSON_6_0 extends WP_Theme_JSON_5_9 {
'palette' => null,
'text' => null,
),
- 'custom' => null,
- 'layout' => array(
+ 'custom' => null,
+ 'layout' => array(
'contentSize' => null,
'wideSize' => null,
+ 'padding' => null,
),
- 'spacing' => array(
+ 'spacing' => array(
'blockGap' => null,
'margin' => null,
'padding' => null,
'units' => null,
),
- 'typography' => array(
+ 'typography' => array(
'customFontSize' => null,
'dropCap' => null,
'fontFamilies' => null,
@@ -325,10 +332,11 @@ protected function get_block_classes( $style_nodes ) {
continue;
}
- $node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
- $selector = $metadata['selector'];
- $settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
- $declarations = static::compute_style_properties( $node, $settings );
+ $use_root_vars = _wp_array_get( $this->theme_json, array( 'settings', 'useRootVariables' ), array() );
+ $node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
+ $selector = $metadata['selector'];
+ $settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
+ $declarations = static::compute_style_properties( $node, $settings, null, $selector, $use_root_vars );
// 1. Separate the ones who use the general selector
// and the ones who use the duotone selector.
@@ -362,6 +370,18 @@ protected function get_block_classes( $style_nodes ) {
}
if ( static::ROOT_BLOCK_SELECTOR === $selector ) {
+ if ( $use_root_vars ) {
+ $block_rules .= '.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }';
+ $block_rules .= '.wp-site-blocks > * { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }';
+
+ // This will be overridden by children who inherit default layout.
+ $block_rules .= '.wp-site-blocks .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); width: auto;}';
+
+ // Alignfull blocks in the block editor that are direct children of post content should also get negative margins.
+ if ( is_callable( 'get_current_screen' ) && get_current_screen()->is_block_editor() ) {
+ $block_rules .= '.is-root-container .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); width: auto; }';
+ }
+ }
$block_rules .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }';
$block_rules .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }';
$block_rules .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
@@ -529,6 +549,143 @@ protected static function get_metadata_boolean( $data, $path, $default = false )
return $default;
}
+ /**
+ * Given a styles array, it extracts the style properties
+ * and adds them to the $declarations array following the format:
+ *
+ * ```php
+ * array(
+ * 'name' => 'property_name',
+ * 'value' => 'property_value,
+ * )
+ * ```
+ *
+ * @param array $styles Styles to process.
+ * @param array $settings Theme settings.
+ * @param array $properties Properties metadata.
+ * @param string $selector Selector for styles.
+ * @param boolean $use_root_vars Whether to use root variables.
+ * @return array Returns the modified $declarations.
+ */
+ protected static function compute_style_properties( $styles, $settings = array(), $properties = null, $selector = null, $use_root_vars = null ) {
+ if ( null === $properties ) {
+ $properties = static::PROPERTIES_METADATA;
+ }
+
+ $declarations = array();
+ $root_variable_duplicates = array();
+
+ if ( empty( $styles ) ) {
+ return $declarations;
+ }
+
+ foreach ( $properties as $css_property => $value_path ) {
+ $value = static::get_property_value( $styles, $value_path );
+
+ if ( strpos( $css_property, '--wp--style--root--' ) === 0 && static::ROOT_BLOCK_SELECTOR !== $selector ) {
+ continue;
+ }
+
+ if ( strpos( $css_property, '--wp--style--root--' ) === 0 && $use_root_vars ) {
+ $root_variable_duplicates[] = substr( $css_property, strlen( '--wp--style--root--' ) );
+ }
+
+ // Root padding requires special logic to split shorthand values.
+ if ( '--wp--style--root--padding' === $css_property && is_string( $value ) ) {
+
+ $shorthand_top = '0';
+ $shorthand_right = '0';
+ $shorthand_bottom = '0';
+ $shorthand_left = '0';
+
+ $separate_values = explode( ' ', $value );
+
+ switch ( count( $separate_values ) ) {
+ case 1:
+ $shorthand_top = $separate_values[0];
+ $shorthand_right = $separate_values[0];
+ $shorthand_bottom = $separate_values[0];
+ $shorthand_left = $separate_values[0];
+ break;
+ case 2:
+ $shorthand_top = $separate_values[0];
+ $shorthand_right = $separate_values[1];
+ $shorthand_bottom = $separate_values[0];
+ $shorthand_left = $separate_values[1];
+ break;
+ case 3:
+ $shorthand_top = $separate_values[0];
+ $shorthand_right = $separate_values[1];
+ $shorthand_bottom = $separate_values[2];
+ $shorthand_left = $separate_values[1];
+ break;
+ case 4:
+ $shorthand_top = $separate_values[0];
+ $shorthand_right = $separate_values[1];
+ $shorthand_bottom = $separate_values[2];
+ $shorthand_left = $separate_values[3];
+ break;
+ }
+
+ $all_properties = array(
+ array(
+ 'name' => '--wp--style--root--padding-top',
+ 'value' => $shorthand_top,
+ ),
+ array(
+ 'name' => '--wp--style--root--padding-right',
+ 'value' => $shorthand_right,
+ ),
+ array(
+ 'name' => '--wp--style--root--padding-bottom',
+ 'value' => $shorthand_bottom,
+ ),
+ array(
+ 'name' => '--wp--style--root--padding-left',
+ 'value' => $shorthand_left,
+ ),
+ );
+
+ $declarations = array_merge( $declarations, $all_properties );
+
+ continue;
+ }
+
+ // Look up protected properties, keyed by value path.
+ // Skip protected properties that are explicitly set to `null`.
+ if ( is_array( $value_path ) ) {
+ $path_string = implode( '.', $value_path );
+ if (
+ array_key_exists( $path_string, static::PROTECTED_PROPERTIES ) &&
+ _wp_array_get( $settings, static::PROTECTED_PROPERTIES[ $path_string ], null ) === null
+ ) {
+ continue;
+ }
+ }
+
+ // Skip if empty and not "0" or value represents array of longhand values.
+ $has_missing_value = empty( $value ) && ! is_numeric( $value );
+ if ( $has_missing_value || is_array( $value ) ) {
+ continue;
+ }
+
+ $declarations[] = array(
+ 'name' => $css_property,
+ 'value' => $value,
+ );
+ }
+
+ // If a variable value is added to the root, the corresponding property should be removed.
+ foreach ( $root_variable_duplicates as $duplicate ) {
+ $discard = array_search( $duplicate, array_column( $declarations, 'name' ), true );
+ if ( $discard ) {
+ array_splice( $declarations, $discard, 1 );
+ }
+ }
+
+ return $declarations;
+ }
+
/**
* Returns a valid theme.json as provided by a theme.
*
diff --git a/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php b/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php
index cc6aa688493de..11c20951d7faf 100644
--- a/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php
+++ b/lib/compat/wordpress-6.0/class-wp-theme-json-resolver-6-0.php
@@ -16,6 +16,7 @@
* @access private
*/
class WP_Theme_JSON_Resolver_6_0 extends WP_Theme_JSON_Resolver_5_9 {
+
/**
* Given a theme.json structure modifies it in place
* to update certain values by its translated strings
diff --git a/lib/compat/wordpress-6.0/theme.json b/lib/compat/wordpress-6.0/theme.json
index 7691aa4a64e6a..631201a70063c 100644
--- a/lib/compat/wordpress-6.0/theme.json
+++ b/lib/compat/wordpress-6.0/theme.json
@@ -2,6 +2,7 @@
"version": 2,
"settings": {
"appearanceTools": false,
+ "useRootVariables": false,
"border": {
"color": false,
"radius": false,
@@ -240,6 +241,14 @@
}
},
"styles": {
- "spacing": { "blockGap": "24px" }
+ "spacing": {
+ "blockGap": "24px",
+ "padding": {
+ "top": "var(--wp--style--block-gap)",
+ "right": "var(--wp--style--block-gap)",
+ "bottom": "var(--wp--style--block-gap)",
+ "left": "var(--wp--style--block-gap)"
+ }
+ }
}
}
diff --git a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php
index d093480e924e4..1ceebf837b183 100644
--- a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php
+++ b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php
@@ -486,6 +486,12 @@ public function get_styles_for_block( $block_metadata ) {
$block_rules = '';
+ $use_root_vars = _wp_array_get( $this->theme_json, array( 'settings', 'useRootVariables' ), array() );
+ $node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() );
+ $selector = $block_metadata['selector'];
+ $settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
+ $declarations = static::compute_style_properties( $node, $settings, null, null, $selector, $use_root_vars );
+
// 1. Separate the ones who use the general selector
// and the ones who use the duotone selector.
$declarations_duotone = array();
@@ -518,6 +524,19 @@ public function get_styles_for_block( $block_metadata ) {
}
if ( static::ROOT_BLOCK_SELECTOR === $selector ) {
+ if ( $use_root_vars ) {
+ $block_rules .= '.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }';
+ $block_rules .= '.wp-site-blocks > * { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }';
+
+ // This will be overridden by children who inherit default layout.
+ $block_rules .= '.wp-site-blocks .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); width: auto;}';
+
+ // Alignfull blocks in the block editor that are direct children of post content should also get negative margins.
+ if ( is_callable( 'get_current_screen' ) && get_current_screen()->is_block_editor() ) {
+ $block_rules .= '.is-root-container .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); width: auto; }';
+ }
+ }
+
$block_rules .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }';
$block_rules .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }';
$block_rules .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
@@ -571,18 +590,21 @@ protected function get_block_classes( $style_nodes ) {
* )
* ```
*
- * @param array $styles Styles to process.
- * @param array $settings Theme settings.
- * @param array $properties Properties metadata.
- * @param array $theme_json Theme JSON array.
- * @return array Returns the modified $declarations.
+ * @param array $styles Styles to process.
+ * @param array $settings Theme settings.
+ * @param array $properties Properties metadata.
+ * @param array $theme_json Theme JSON array.
+ * @param string $selector Selector for styles.
+ * @param boolean $use_root_vars Whether to use root.
+ * @return array Returns the modified $declarations.
*/
- protected static function compute_style_properties( $styles, $settings = array(), $properties = null, $theme_json = null ) {
+ protected static function compute_style_properties( $styles, $settings = array(), $properties = null, $theme_json = null, $selector = null, $use_root_vars = null ) {
if ( null === $properties ) {
$properties = static::PROPERTIES_METADATA;
}
- $declarations = array();
+ $declarations = array();
+ $root_variable_duplicates = array();
if ( empty( $styles ) ) {
return $declarations;
}
@@ -590,6 +612,75 @@ protected static function compute_style_properties( $styles, $settings = array()
foreach ( $properties as $css_property => $value_path ) {
$value = static::get_property_value( $styles, $value_path, $theme_json );
+ if ( strpos( $css_property, '--wp--style--root--' ) === 0 && static::ROOT_BLOCK_SELECTOR !== $selector ) {
+ continue;
+ }
+
+ if ( strpos( $css_property, '--wp--style--root--' ) === 0 && $use_root_vars ) {
+ $root_variable_duplicates[] = substr( $css_property, strlen( '--wp--style--root--' ) );
+ }
+
+ // Root padding requires special logic to split shorthand values.
+ if ( '--wp--style--root--padding' === $css_property && is_string( $value ) ) {
+
+ $shorthand_top = '0';
+ $shorthand_right = '0';
+ $shorthand_bottom = '0';
+ $shorthand_left = '0';
+
+ $separate_values = explode( ' ', $value );
+
+ switch ( count( $separate_values ) ) {
+ case 1:
+ $shorthand_top = $separate_values[0];
+ $shorthand_right = $separate_values[0];
+ $shorthand_bottom = $separate_values[0];
+ $shorthand_left = $separate_values[0];
+ break;
+ case 2:
+ $shorthand_top = $separate_values[0];
+ $shorthand_right = $separate_values[1];
+ $shorthand_bottom = $separate_values[0];
+ $shorthand_left = $separate_values[1];
+ break;
+ case 3:
+ $shorthand_top = $separate_values[0];
+ $shorthand_right = $separate_values[1];
+ $shorthand_bottom = $separate_values[2];
+ $shorthand_left = $separate_values[1];
+ break;
+ case 4:
+ $shorthand_top = $separate_values[0];
+ $shorthand_right = $separate_values[1];
+ $shorthand_bottom = $separate_values[2];
+ $shorthand_left = $separate_values[3];
+ break;
+ }
+
+ $all_properties = array(
+ array(
+ 'name' => '--wp--style--root--padding-top',
+ 'value' => $shorthand_top,
+ ),
+ array(
+ 'name' => '--wp--style--root--padding-right',
+ 'value' => $shorthand_right,
+ ),
+ array(
+ 'name' => '--wp--style--root--padding-bottom',
+ 'value' => $shorthand_bottom,
+ ),
+ array(
+ 'name' => '--wp--style--root--padding-left',
+ 'value' => $shorthand_left,
+ ),
+ );
+
+ $declarations = array_merge( $declarations, $all_properties );
+
+ continue;
+ }
+
// Look up protected properties, keyed by value path.
// Skip protected properties that are explicitly set to `null`.
if ( is_array( $value_path ) ) {
@@ -614,6 +705,14 @@ protected static function compute_style_properties( $styles, $settings = array()
);
}
+ // If a variable value is added to the root, the corresponding property should be removed.
+ foreach ( $root_variable_duplicates as $duplicate ) {
+ $discard = array_search( $duplicate, array_column( $declarations, 'name' ), true );
+ if ( $discard ) {
+ array_splice( $declarations, $discard, 1 );
+ }
+ }
+
return $declarations;
}
diff --git a/packages/block-editor/src/components/block-list/style.scss b/packages/block-editor/src/components/block-list/style.scss
index 7b78148328aec..51156e4b3af90 100644
--- a/packages/block-editor/src/components/block-list/style.scss
+++ b/packages/block-editor/src/components/block-list/style.scss
@@ -308,6 +308,22 @@
}
}
+// Active entity spotlight.
+// Disable if focus mode is active.
+.is-root-container:not(.is-focus-mode) .block-editor-block-list__block.has-active-entity {
+ opacity: 0.5;
+ transition: opacity 0.1s linear;
+ @include reduce-motion("transition");
+
+ &.is-active-entity,
+ &.has-child-selected,
+ &:not(.has-child-selected) .block-editor-block-list__block,
+ &.is-active-entity .block-editor-block-list__block,
+ .is-active-entity .block-editor-block-list__block {
+ opacity: 1;
+ }
+}
+
.wp-block[data-align="left"] > *,
.wp-block[data-align="right"] > *,
.wp-block.alignleft,
diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js
index c5072200869ed..eeb01a45f5b51 100644
--- a/packages/block-editor/src/hooks/layout.js
+++ b/packages/block-editor/src/hooks/layout.js
@@ -2,7 +2,7 @@
* External dependencies
*/
import classnames from 'classnames';
-import { has, kebabCase } from 'lodash';
+import { has, get, kebabCase } from 'lodash';
/**
* WordPress dependencies
@@ -77,23 +77,14 @@ function getLayoutClasses( attributes ) {
function LayoutPanel( { setAttributes, attributes, name: blockName } ) {
const { layout } = attributes;
- const defaultThemeLayout = useSetting( 'layout' );
- const themeSupportsLayout = useSelect( ( select ) => {
- const { getSettings } = select( blockEditorStore );
- return getSettings().supportsLayout;
- }, [] );
- const layoutBlockSupport = getBlockSupport(
- blockName,
- layoutBlockSupportKey,
- {}
- );
+ const { supportsFlowLayout, config } = useLayout( blockName );
const {
allowSwitching,
allowEditing = true,
allowInheriting = true,
default: defaultBlockLayout,
- } = layoutBlockSupport;
+ } = config;
if ( ! allowEditing ) {
return null;
@@ -104,18 +95,14 @@ function LayoutPanel( { setAttributes, attributes, name: blockName } ) {
// and that the default / flow layout type is in use, as this is the only one that supports inheritance.
const showInheritToggle = !! (
allowInheriting &&
- !! defaultThemeLayout &&
+ !! supportsFlowLayout &&
( ! layout?.type || layout?.type === 'default' || layout?.inherit )
);
const usedLayout = layout || defaultBlockLayout || {};
const { inherit = false, type = 'default' } = usedLayout;
- /**
- * `themeSupportsLayout` is only relevant to the `default/flow`
- * layout and it should not be taken into account when other
- * `layout` types are used.
- */
- if ( type === 'default' && ! themeSupportsLayout ) {
+
+ if ( type === 'default' && ! supportsFlowLayout ) {
return null;
}
const layoutType = getLayoutType( type );
@@ -163,7 +150,7 @@ function LayoutPanel( { setAttributes, attributes, name: blockName } ) {
) }
@@ -172,7 +159,7 @@ function LayoutPanel( { setAttributes, attributes, name: blockName } ) {
) }
>
@@ -197,6 +184,26 @@ function LayoutTypeSwitcher( { type, onChange } ) {
);
}
+export function useLayout( blockName ) {
+ const defaultThemeLayout = useSetting( 'layout' );
+ const themeSupportsLayout = useSelect( ( select ) => {
+ const { getSettings } = select( blockEditorStore );
+ return getSettings().supportsLayout;
+ }, [] );
+
+ const layoutBlockSupport = getBlockSupport(
+ blockName,
+ layoutBlockSupportKey,
+ {}
+ );
+
+ return {
+ supportsFlowLayout: themeSupportsLayout,
+ defaultLayout: defaultThemeLayout,
+ config: layoutBlockSupport,
+ };
+}
+
/**
* Filters registered block settings, extending attributes to include `layout`.
*
@@ -276,6 +283,9 @@ export const withLayoutStyles = createHigherOrderComponent(
},
layoutClasses
);
+ const padding = layout?.inherit
+ ? usedLayout?.padding
+ : get( attributes, [ 'style', 'spacing', 'padding' ] );
return (
<>
@@ -286,6 +296,7 @@ export const withLayoutStyles = createHigherOrderComponent(
blockName={ name }
selector={ `.wp-container-${ id }` }
layout={ usedLayout }
+ padding={ padding }
style={ attributes?.style }
/>,
element
diff --git a/packages/block-editor/src/hooks/padding.js b/packages/block-editor/src/hooks/padding.js
index 02a371db0d6a3..495ea70570e59 100644
--- a/packages/block-editor/src/hooks/padding.js
+++ b/packages/block-editor/src/hooks/padding.js
@@ -28,6 +28,7 @@ import {
} from './dimensions';
import { cleanEmptyObject } from './utils';
import BlockPopover from '../components/block-popover';
+import { useLayout } from './layout';
/**
* Determines if there is padding support.
@@ -80,11 +81,19 @@ export function resetPadding( { attributes = {}, setAttributes } ) {
*
* @return {boolean} Whether padding setting is disabled.
*/
-export function useIsPaddingDisabled( { name: blockName } = {} ) {
+export function useIsPaddingDisabled( { name: blockName, attributes } = {} ) {
+ const { supportsFlowLayout, config } = useLayout( blockName );
+ const hasInheritedLayout =
+ supportsFlowLayout && !! config && attributes?.layout?.inherit;
const isDisabled = ! useSetting( 'spacing.padding' );
const isInvalid = ! useIsDimensionsSupportValid( blockName, 'padding' );
- return ! hasPaddingSupport( blockName ) || isDisabled || isInvalid;
+ return (
+ ! hasPaddingSupport( blockName ) ||
+ hasInheritedLayout ||
+ isDisabled ||
+ isInvalid
+ );
}
/**
diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js
index 400ebd0a84263..fd4c4fdc8b9fa 100644
--- a/packages/block-editor/src/hooks/style.js
+++ b/packages/block-editor/src/hooks/style.js
@@ -68,6 +68,9 @@ export function getInlineStyles( styles = {} ) {
const ignoredStyles = [ 'spacing.blockGap' ];
const output = {};
Object.keys( STYLE_PROPERTY ).forEach( ( propKey ) => {
+ if ( STYLE_PROPERTY[ propKey ].rootOnly ) {
+ return;
+ }
const path = STYLE_PROPERTY[ propKey ].value;
const subPaths = STYLE_PROPERTY[ propKey ].properties;
// Ignore styles on elements because they are handled on the server.
diff --git a/packages/block-editor/src/layouts/flow.js b/packages/block-editor/src/layouts/flow.js
index 82851cb015075..4c263ea4daf21 100644
--- a/packages/block-editor/src/layouts/flow.js
+++ b/packages/block-editor/src/layouts/flow.js
@@ -112,6 +112,7 @@ export default {
layout = {},
style,
blockName,
+ padding,
} ) {
const { contentSize, wideSize } = layout;
const blockGapSupport = useSetting( 'spacing.blockGap' );
@@ -126,13 +127,20 @@ export default {
! shouldSkipSerialization( blockName, 'spacing', 'blockGap' )
? blockGapStyleValue?.top
: 'var( --wp--style--block-gap )';
+ // Using important here for the padding to override the inline padding that could be potentially
+ // applied using the custom padding control before the layout inheritance is applied.
let output =
!! contentSize || !! wideSize
? `
+ ${ appendSelectors( selector ) } {
+ padding: ${ padding?.top || 0 } ${ padding?.right || 0 } ${
+ padding?.bottom || 0
+ } ${ padding?.left || 0 } !important;
+ }
${ appendSelectors(
selector,
- '> :where(:not(.alignleft):not(.alignright))'
+ '> :where(:not(.alignleft):not(.alignright):not(.alignfull))'
) } {
max-width: ${ contentSize ?? wideSize };
margin-left: auto !important;
@@ -143,6 +151,16 @@ export default {
}
${ appendSelectors( selector, '> .alignfull' ) } {
max-width: none;
+ ${
+ padding?.left
+ ? `margin-left: calc( -1 * ${ padding?.left } ) !important;`
+ : ''
+ }
+ ${
+ padding?.right
+ ? `margin-right: calc( -1 * ${ padding?.right } ) !important;`
+ : ''
+ }
}
`
: '';
diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js
index b7e9d11524ac7..ee2e1f8a0d8cb 100644
--- a/packages/blocks/src/api/constants.js
+++ b/packages/blocks/src/api/constants.js
@@ -203,6 +203,17 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = {
value: [ 'spacing', 'blockGap' ],
support: [ 'spacing', 'blockGap' ],
},
+ '--wp--style--root--padding': {
+ value: [ 'spacing', 'padding' ],
+ support: [ 'spacing', 'padding' ],
+ properties: {
+ '--wp--style--root--padding-top': 'top',
+ '--wp--style--root--padding-right': 'right',
+ '--wp--style--root--padding-bottom': 'bottom',
+ '--wp--style--root--padding-left': 'left',
+ },
+ rootOnly: true,
+ },
};
export const __EXPERIMENTAL_ELEMENTS = {
diff --git a/packages/edit-post/src/components/visual-editor/index.js b/packages/edit-post/src/components/visual-editor/index.js
index b5a2b0a4a4b97..a0ef01533a92e 100644
--- a/packages/edit-post/src/components/visual-editor/index.js
+++ b/packages/edit-post/src/components/visual-editor/index.js
@@ -198,6 +198,14 @@ export default function VisualEditor( { styles } ) {
titleRef?.current?.focus();
}, [ isWelcomeGuideVisible, isCleanNewPost ] );
+ const padding = useMemo( () => {
+ if ( isTemplateMode || ! themeSupportsLayout ) {
+ return undefined;
+ }
+
+ return defaultLayout?.padding;
+ } );
+
return (
) }
{ ! isTemplateMode && (
diff --git a/packages/edit-site/src/components/global-styles/test/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/test/use-global-styles-output.js
index 10e1d533e025b..1ea6261e6d3d1 100644
--- a/packages/edit-site/src/components/global-styles/test/use-global-styles-output.js
+++ b/packages/edit-site/src/components/global-styles/test/use-global-styles-output.js
@@ -443,10 +443,7 @@ describe( 'global styles renderer', () => {
};
expect( toStyles( tree, blockSelectors ) ).toEqual(
- 'body {margin: 0;}' +
- 'body{background-color: red;margin: 10px;padding: 10px;}h1{font-size: 42px;}a{color: blue;}a:hover{color: orange;}a:focus{color: orange;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{color: red;}h1 a:focus,h2 a:focus,h3 a:focus,h4 a:focus,h5 a:focus,h6 a:focus{color: red;}' +
- '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' +
- '.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}'
+ '.wp-site-blocks > * { margin-top: 0; margin-bottom: 0; }.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); }body{background-color: red;--wp--style--root--padding-top: 10px;--wp--style--root--padding-right: 10px;--wp--style--root--padding-bottom: 10px;--wp--style--root--padding-left: 10px;margin: 10px;padding: 10px;}h1{font-size: 42px;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}'
);
} );
} );
diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js
index 9a8ad4f54282b..4b1a1df822393 100644
--- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js
+++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js
@@ -170,14 +170,21 @@ function flattenTree( input = {}, prefix, token ) {
/**
* Transform given style tree into a set of style declarations.
*
- * @param {Object} blockStyles Block styles.
+ * @param {Object} blockStyles Block styles.
*
+ * @param {string} selector The selector these declarations should attach to.
+ *
+ * @param {boolean} useRootVars Whether to use CSS custom properties in root selector.
* @return {Array} An array of style declarations.
*/
-function getStylesDeclarations( blockStyles = {} ) {
+function getStylesDeclarations( blockStyles = {}, selector = '', useRootVars ) {
+ const isRoot = ROOT_BLOCK_SELECTOR === selector;
const output = reduce(
STYLE_PROPERTY,
- ( declarations, { value, properties, useEngine }, key ) => {
+ ( declarations, { value, properties, useEngine, rootOnly }, key ) => {
+ if ( rootOnly && ! isRoot ) {
+ return declarations;
+ }
const pathToValue = value;
if ( first( pathToValue ) === 'elements' || useEngine ) {
return declarations;
@@ -194,14 +201,63 @@ function getStylesDeclarations( blockStyles = {} ) {
// for sub-properties that don't have any value.
return;
}
-
- const cssProperty = kebabCase( name );
+ const cssProperty = name.startsWith( '--' )
+ ? name
+ : kebabCase( name );
declarations.push(
`${ cssProperty }: ${ compileStyleValue(
get( styleValue, [ prop ] )
) }`
);
} );
+ } else if ( !! properties && isString( styleValue ) && rootOnly ) {
+ const separateValues = styleValue.split( ' ' );
+
+ const sortedBoxValues = {
+ top: '0',
+ right: '0',
+ bottom: '0',
+ left: '0',
+ };
+
+ switch ( separateValues.length ) {
+ case 1:
+ sortedBoxValues.top = separateValues[ 0 ];
+ sortedBoxValues.right = separateValues[ 0 ];
+ sortedBoxValues.bottom = separateValues[ 0 ];
+ sortedBoxValues.left = separateValues[ 0 ];
+ break;
+ case 2:
+ sortedBoxValues.top = separateValues[ 0 ];
+ sortedBoxValues.right = separateValues[ 1 ];
+ sortedBoxValues.bottom = separateValues[ 0 ];
+ sortedBoxValues.left = separateValues[ 1 ];
+ break;
+ case 3:
+ sortedBoxValues.top = separateValues[ 0 ];
+ sortedBoxValues.right = separateValues[ 1 ];
+ sortedBoxValues.bottom = separateValues[ 2 ];
+ sortedBoxValues.left = separateValues[ 1 ];
+ break;
+ case 4:
+ sortedBoxValues.top = separateValues[ 0 ];
+ sortedBoxValues.right = separateValues[ 1 ];
+ sortedBoxValues.bottom = separateValues[ 2 ];
+ sortedBoxValues.left = separateValues[ 3 ];
+ break;
+ }
+
+ Object.entries( properties ).forEach( ( entry ) => {
+ const [ name, prop ] = entry;
+ const cssProperty = name.startsWith( '--' )
+ ? name
+ : kebabCase( name );
+ declarations.push(
+ `${ cssProperty }: ${ compileStyleValue(
+ get( sortedBoxValues, [ prop ] )
+ ) }`
+ );
+ } );
} else if ( get( blockStyles, pathToValue, false ) ) {
const cssProperty = key.startsWith( '--' )
? key
@@ -218,6 +274,10 @@ function getStylesDeclarations( blockStyles = {} ) {
[]
);
+ if ( isRoot && useRootVars ) {
+ return output;
+ }
+
// The goal is to move everything to server side generated engine styles
// This is temporary as we absorb more and more styles into the engine.
const extraRules = getCSSRules( blockStyles );
@@ -367,6 +427,7 @@ export const toCustomProperties = ( tree, blockSelectors ) => {
export const toStyles = ( tree, blockSelectors, hasBlockGapSupport ) => {
const nodesWithStyles = getNodesWithStyles( tree, blockSelectors );
const nodesWithSettings = getNodesWithSettings( tree, blockSelectors );
+ const useRootVars = tree?.settings?.useRootVariables;
/*
* Reset default browser margin on the root body element.
@@ -377,6 +438,11 @@ export const toStyles = ( tree, blockSelectors, hasBlockGapSupport ) => {
* @link https://github.com/WordPress/gutenberg/issues/36147.
*/
let ruleset = 'body {margin: 0;}';
+ if ( useRootVars ) {
+ ruleset =
+ 'body { margin: 0; padding-right: 0; padding-left: 0; padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom) } .wp-site-blocks > * { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); } }';
+ }
+
nodesWithStyles.forEach( ( { selector, duotoneSelector, styles } ) => {
const duotoneStyles = {};
if ( styles?.filter ) {
@@ -396,7 +462,12 @@ export const toStyles = ( tree, blockSelectors, hasBlockGapSupport ) => {
}
// Process the remaning block styles (they use either normal block class or __experimentalSelector).
- const declarations = getStylesDeclarations( styles );
+ const declarations = getStylesDeclarations(
+ styles,
+ selector,
+ useRootVars
+ );
+
if ( declarations?.length ) {
ruleset = ruleset + `${ selector }{${ declarations.join( ';' ) };}`;
}
diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php
index ed5b867e77534..6129acc0df258 100644
--- a/phpunit/class-wp-theme-json-test.php
+++ b/phpunit/class-wp-theme-json-test.php
@@ -351,7 +351,7 @@ function test_get_stylesheet_support_for_shorthand_and_longhand_values() {
)
);
- $styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-group{border-radius: 10px;margin: 1em;padding: 24px;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;padding-top: 15px;}';
+ $styles = 'body { margin: 0; }body{--wp--style--root--padding-top: ;--wp--style--root--padding-right: ;--wp--style--root--padding-bottom: ;--wp--style--root--padding-left: ;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-group{border-radius: 10px;margin: 1em;padding: 24px;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;padding-top: 15px;}';
$this->assertEquals( $styles, $theme_json->get_stylesheet() );
$this->assertEquals( $styles, $theme_json->get_stylesheet( array( 'styles' ) ) );
}
@@ -380,7 +380,7 @@ function test_get_stylesheet_skips_disabled_protected_properties() {
)
);
- $expected = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
+ $expected = 'body { margin: 0; }body{--wp--style--root--padding-top: ;--wp--style--root--padding-right: ;--wp--style--root--padding-bottom: ;--wp--style--root--padding-left: ;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }';
$this->assertEquals( $expected, $theme_json->get_stylesheet() );
$this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) );
}
@@ -402,7 +402,7 @@ function test_get_stylesheet_renders_enabled_protected_properties() {
)
);
- $expected = 'body { margin: 0; }body{--wp--style--block-gap: 1em;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }';
+ $expected = 'body { margin: 0; }body{--wp--style--root--padding-top: ;--wp--style--root--padding-right: ;--wp--style--root--padding-bottom: ;--wp--style--root--padding-left: ;--wp--style--block-gap: 1em;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }';
$this->assertEquals( $expected, $theme_json->get_stylesheet() );
$this->assertEquals( $expected, $theme_json->get_stylesheet( array( 'styles' ) ) );
}
@@ -528,7 +528,7 @@ function test_get_stylesheet() {
);
$variables = 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}';
- $styles = 'body { margin: 0; }body{color: var(--wp--preset--color--grey);}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }a{background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}';
+ $styles = 'body { margin: 0; }body{color: var(--wp--preset--color--grey);--wp--style--root--padding-top: ;--wp--style--root--padding-right: ;--wp--style--root--padding-bottom: ;--wp--style--root--padding-left: ;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-site-blocks > * { margin-block-start: 0; margin-block-end: 0; }.wp-site-blocks > * + * { margin-block-start: var( --wp--style--block-gap ); }a{background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}';
$presets = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-small-font-family{font-family: var(--wp--preset--font-family--small) !important;}.has-big-font-family{font-family: var(--wp--preset--font-family--big) !important;}';
$all = $variables . $styles . $presets;
$this->assertEquals( $all, $theme_json->get_stylesheet() );
@@ -594,7 +594,7 @@ function test_get_stylesheet_preset_rules_come_after_block_rules() {
)
);
- $styles = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-group{color: red;}';
+ $styles = 'body { margin: 0; }body{--wp--style--root--padding-top: ;--wp--style--root--padding-right: ;--wp--style--root--padding-bottom: ;--wp--style--root--padding-left: ;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.wp-block-group{color: red;}';
$presets = '.wp-block-group.has-grey-color{color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.wp-block-group.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}';
$variables = '.wp-block-group{--wp--preset--color--grey: grey;}';
$all = $variables . $styles . $presets;
@@ -680,7 +680,7 @@ public function test_get_stylesheet_preset_values_are_marked_as_important() {
);
$this->assertEquals(
- 'body{--wp--preset--color--grey: grey;}body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }p{background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}',
+ 'body{--wp--preset--color--grey: grey;}body { margin: 0; }body{--wp--style--root--padding-top: ;--wp--style--root--padding-right: ;--wp--style--root--padding-bottom: ;--wp--style--root--padding-left: ;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }p{background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}',
$theme_json->get_stylesheet()
);
}