diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 23f10b9453682..b4b63da3c339d 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2518,6 +2518,7 @@ private static function get_block_nodes( $theme_json, $selectors = array() ) { * Gets the CSS rules for a particular block from theme.json. * * @since 6.1.0 + * @since 6.6.0 Setting a min-height of HTML when root styles have a background gradient or image. * * @param array $block_metadata Metadata about the block to get styles for. * @@ -2528,6 +2529,7 @@ public function get_styles_for_block( $block_metadata ) { $use_root_padding = isset( $this->theme_json['settings']['useRootPaddingAwareAlignments'] ) && true === $this->theme_json['settings']['useRootPaddingAwareAlignments']; $selector = $block_metadata['selector']; $settings = $this->theme_json['settings'] ?? null; + $is_root_selector = static::ROOT_BLOCK_SELECTOR === $selector; $feature_declarations = static::get_feature_declarations_for_node( $block_metadata, $node ); @@ -2613,10 +2615,16 @@ static function ( $pseudo_selector ) use ( $selector ) { $block_rules = ''; /* - * 1. Separate the declarations that use the general selector + * 1. Bespoke declaration modifiers: + * - 'filter': Separate the declarations that use the general selector * from the ones using the duotone selector. + * - 'background|background-image': set the html min-height to 100% + * to ensure the background covers the entire viewport. + * */ - $declarations_duotone = array(); + $declarations_duotone = array(); + $should_set_root_min_height = false; + foreach ( $declarations as $index => $declaration ) { if ( 'filter' === $declaration['name'] ) { /* @@ -2633,6 +2641,28 @@ static function ( $pseudo_selector ) use ( $selector ) { } unset( $declarations[ $index ] ); } + + if ( $is_root_selector && ( 'background-image' === $declaration['name'] || 'background' === $declaration['name'] ) ) { + $should_set_root_min_height = true; + } + } + + /* + * If root styles has a background-image or a background (gradient) set, + * set the min-height to '100%'. Minus `--wp-admin--admin-bar--height` for logged-in view. + * Setting the CSS rule on the HTML tag ensures background gradients and images behave similarly, + * and matches the behavior of the site editor. + */ + if ( $should_set_root_min_height ) { + $block_rules .= static::to_ruleset( + 'html', + array( + array( + 'name' => 'min-height', + 'value' => 'calc(100% - var(--wp-admin--admin-bar--height, 0px))', + ), + ) + ); } // Update declarations if there are separators with only background color defined. @@ -2650,7 +2680,7 @@ static function ( $pseudo_selector ) use ( $selector ) { // 4. Generate Layout block gap styles. if ( - static::ROOT_BLOCK_SELECTOR !== $selector && + ! $is_root_selector && ! empty( $block_metadata['name'] ) ) { $block_rules .= $this->get_layout_styles( $block_metadata ); diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 09e0e9880664c..31f0d7e38c095 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -4802,7 +4802,7 @@ public function test_get_top_level_background_image_styles() { 'backgroundImage' => array( 'url' => 'http://example.org/image.png', ), - 'backgroundSize' => 'cover', + 'backgroundSize' => 'contain', 'backgroundRepeat' => 'no-repeat', 'backgroundPosition' => 'center center', ), @@ -4835,7 +4835,7 @@ public function test_get_top_level_background_image_styles() { ) ); - $expected_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; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}body .is-layout-flex > *{margin: 0;}body .is-layout-grid{display: grid;}body .is-layout-grid > *{margin: 0;}body{background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: cover;}"; + $expected_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; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}body .is-layout-flex > *{margin: 0;}body .is-layout-grid{display: grid;}body .is-layout-grid > *{margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}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_stylesheet() ); }