Commit 252be4e9dcc for woocommerce
commit 252be4e9dccc245671f6f218fe30e1eefa94c3cb
Author: Jan Lysý <lysyjan@users.noreply.github.com>
Date: Wed Apr 8 10:46:52 2026 +0200
Fix email editor styling regressions in block emails (#63974)
* Fix email editor styling regressions in block emails
The block email editor had three styling issues caused by a CSS selector
mismatch between the traditional WC email system (#body_content scoping)
and the block email DOM structure (.email_layout_wrapper):
1. Logo/title font competition: theme.json set heading fontWeight to 400,
while WC CSS overrode headings to 20px bold — making logo and title
visually identical. Fixed by setting heading fontWeight to 700 in
theme.json and adding core/site-title block styles (11px, 500 weight,
uppercase, #757575) for clear visual hierarchy.
2. Totals bold inconsistency: all totals rows appeared bold because
email-styles.php rules were scoped to #body_content (absent in block
emails), leaving <th> elements with browser-default bold. Fixed by
adding targeted CSS in WooContentProcessor::get_woo_content_styles()
that sets font-weight 400 for regular rows and 700 for the Total row.
3. Incorrect indentation: root padding (20px) plus spacing preset (20px)
gave 40px horizontal padding instead of the expected 48px. Fixed by
updating both values to 24px in theme.json.
Additional changes:
- WooContentProcessor::prepare_css() now strips font-size, font-weight,
line-height, and letter-spacing from WC CSS to prevent overriding the
editor theme typography
- Added get_woo_content_styles() for block-email-specific CSS (order
totals, section headings, item metadata)
- Removed stale PHPStan baseline entries resolved by (string) cast
- Added unit tests for prepare_css() and get_woo_content_styles()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add changefile(s) from automation for the following project(s): packages/php/email-editor, woocommerce
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
diff --git a/packages/php/email-editor/changelog/63974-fix-email-editor-styling-regressions b/packages/php/email-editor/changelog/63974-fix-email-editor-styling-regressions
new file mode 100644
index 00000000000..382c39536c0
--- /dev/null
+++ b/packages/php/email-editor/changelog/63974-fix-email-editor-styling-regressions
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix email editor styling regressions: logo/title font competition, inconsistent bold in order totals, and incorrect content indentation in block emails.
\ No newline at end of file
diff --git a/packages/php/email-editor/src/Engine/theme.json b/packages/php/email-editor/src/Engine/theme.json
index 9d71d7e3057..d5f139fca47 100644
--- a/packages/php/email-editor/src/Engine/theme.json
+++ b/packages/php/email-editor/src/Engine/theme.json
@@ -33,7 +33,7 @@
},
{
"name": "2",
- "size": "20px",
+ "size": "24px",
"slug": "20"
},
{
@@ -225,10 +225,10 @@
"spacing": {
"blockGap": "16px",
"padding": {
- "bottom": "20px",
- "left": "20px",
- "right": "20px",
- "top": "20px"
+ "bottom": "24px",
+ "left": "24px",
+ "right": "24px",
+ "top": "24px"
}
},
"color": {
@@ -245,10 +245,23 @@
"textDecoration": "none",
"textTransform": "none"
},
+ "blocks": {
+ "core/site-title": {
+ "typography": {
+ "fontSize": "11px",
+ "fontWeight": "500",
+ "letterSpacing": "0.55px",
+ "textTransform": "uppercase"
+ },
+ "color": {
+ "text": "#757575"
+ }
+ }
+ },
"elements": {
"heading": {
"typography": {
- "fontWeight": "400",
+ "fontWeight": "700",
"fontStyle": "normal",
"lineHeight": "1.2"
}
diff --git a/plugins/woocommerce/changelog/63974-fix-email-editor-styling-regressions b/plugins/woocommerce/changelog/63974-fix-email-editor-styling-regressions
new file mode 100644
index 00000000000..382c39536c0
--- /dev/null
+++ b/plugins/woocommerce/changelog/63974-fix-email-editor-styling-regressions
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix email editor styling regressions: logo/title font competition, inconsistent bold in order totals, and incorrect content indentation in block emails.
\ No newline at end of file
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 1ab25cfc4d6..bc079f8d320 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -65053,17 +65053,6 @@ parameters:
count: 1
path: src/Internal/EmailEditor/WCTransactionalEmails/WCTransactionalEmails.php
- -
- message: '#^Method Automattic\\WooCommerce\\Internal\\EmailEditor\\WooContentProcessor\:\:prepare_css\(\) should return string but returns string\|null\.$#'
- identifier: return.type
- count: 1
- path: src/Internal/EmailEditor/WooContentProcessor.php
-
- -
- message: '#^Parameter \#3 \$subject of function preg_replace expects array\<float\|int\|string\>\|string, string\|null given\.$#'
- identifier: argument.type
- count: 1
- path: src/Internal/EmailEditor/WooContentProcessor.php
-
message: '#^@param string \$feature_id does not accept actual type of parameter\: int\<min, \-1\>\|int\<1, max\>\|non\-falsy\-string\.$#'
diff --git a/plugins/woocommerce/src/Internal/EmailEditor/EmailTemplates/WooEmailTemplate.php b/plugins/woocommerce/src/Internal/EmailEditor/EmailTemplates/WooEmailTemplate.php
index ae5f5704982..0c688c5fc8f 100644
--- a/plugins/woocommerce/src/Internal/EmailEditor/EmailTemplates/WooEmailTemplate.php
+++ b/plugins/woocommerce/src/Internal/EmailEditor/EmailTemplates/WooEmailTemplate.php
@@ -80,6 +80,6 @@ class WooEmailTemplate {
return '<!-- wp:site-logo {"width":130,"isLink":false,"align":"center","style":{"spacing":{"padding":{"top":"var:preset|spacing|10","bottom":"var:preset|spacing|10"}}}} /-->';
}
- return '<!-- wp:site-title {"level":2,"textAlign":"center","style":{"spacing":{"padding":{"top":"var:preset|spacing|10","bottom":"var:preset|spacing|10"}}}} /-->';
+ return '<!-- wp:site-title {"level":2,"style":{"spacing":{"padding":{"top":"var:preset|spacing|10","bottom":"var:preset|spacing|10"}}}} /-->';
}
}
diff --git a/plugins/woocommerce/src/Internal/EmailEditor/WooContentProcessor.php b/plugins/woocommerce/src/Internal/EmailEditor/WooContentProcessor.php
index 6dbdbf20090..0b83263238f 100644
--- a/plugins/woocommerce/src/Internal/EmailEditor/WooContentProcessor.php
+++ b/plugins/woocommerce/src/Internal/EmailEditor/WooContentProcessor.php
@@ -49,18 +49,33 @@ class WooContentProcessor {
/**
* Filter CSS for the email.
- * The CSS was from email editor was already inlined.
- * The method hookes to woocommerce_email_styles and removes CSS rules that we don't want to apply to the email.
+ * The CSS from the email editor was already inlined.
+ * The method hooks to woocommerce_email_styles and removes CSS rules that we don't want to apply to the email.
*
+ * Typography properties (font-size, font-weight, line-height, letter-spacing) are stripped
+ * because the email editor theme controls all typography via theme.json. Leaving these in
+ * the WooCommerce CSS would override the editor's heading sizes and weights.
+ *
+ * @since 10.8.0
* @param string $css CSS.
* @return string
*/
public function prepare_css( string $css ): string {
remove_filter( 'woocommerce_email_styles', array( $this, 'prepare_css' ) );
- // Remove color and font-family declarations from WooCommerce CSS.
- $css = preg_replace( '/color\s*:\s*[^;]+;/', '', $css );
- $css = preg_replace( '/font-family\s*:\s*[^;]+;/', '', $css );
- return $css;
+ // Remove typography declarations from WooCommerce CSS.
+ // The email editor theme.json controls all typography; WC CSS would override it.
+ return (string) preg_replace(
+ array(
+ '/color\s*:\s*[^;]+;/',
+ '/font-family\s*:\s*[^;]+;/',
+ '/font-size\s*:\s*[^;]+;/',
+ '/font-weight\s*:\s*[^;]+;/',
+ '/line-height\s*:\s*[^;]+;/',
+ '/letter-spacing\s*:\s*[^;]+;/',
+ ),
+ '',
+ $css
+ );
}
/**
@@ -87,10 +102,74 @@ class WooContentProcessor {
if ( empty( $woo_content ) ) {
return '';
}
- $css = $this->theme_controller->get_stylesheet_for_rendering();
+ $css = $this->theme_controller->get_stylesheet_for_rendering();
+ $css .= $this->get_woo_content_styles();
return $this->css_inliner->from_html( $woo_content )->inline_css( $css )->render();
}
+ /**
+ * Get CSS styles specific to WooCommerce email content.
+ *
+ * These styles target WooCommerce-specific HTML classes in the order details,
+ * totals, and other email content areas. They are needed because the WooCommerce
+ * email CSS selectors (prefixed with #body_content) do not match in the block
+ * email editor template structure.
+ *
+ * @since 10.8.0
+ * @return string CSS styles.
+ */
+ private function get_woo_content_styles(): string {
+ return '
+ .email-order-details td,
+ .email-order-details th {
+ padding: 8px 12px;
+ }
+ .email-order-details td:first-child,
+ .email-order-details th:first-child {
+ padding-left: 0;
+ }
+ .email-order-details td:last-child,
+ .email-order-details th:last-child {
+ padding-right: 0;
+ }
+ .order-item-data td {
+ border: 0;
+ padding: 0;
+ vertical-align: top;
+ }
+ .order-item-data img {
+ border-radius: 4px;
+ }
+ .order-totals th,
+ .order-totals td {
+ font-weight: 400;
+ padding-bottom: 5px;
+ padding-top: 5px;
+ }
+ .order-totals-total th {
+ font-weight: 700;
+ }
+ .order-totals-total td {
+ font-weight: 700;
+ font-size: 20px;
+ }
+ h2.email-order-detail-heading {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.6;
+ }
+ h2.email-order-detail-heading span {
+ font-size: 14px;
+ font-weight: 400;
+ color: #757575;
+ }
+ .email-order-item-meta {
+ font-size: 14px;
+ line-height: 1.4;
+ }
+ ';
+ }
+
/**
* Capture the WooCommerce content excluding headers and footers.
*
diff --git a/plugins/woocommerce/tests/php/src/Internal/EmailEditor/WooContentProcessorTest.php b/plugins/woocommerce/tests/php/src/Internal/EmailEditor/WooContentProcessorTest.php
index ed06a407284..b267b2738f5 100644
--- a/plugins/woocommerce/tests/php/src/Internal/EmailEditor/WooContentProcessorTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/EmailEditor/WooContentProcessorTest.php
@@ -23,6 +23,43 @@ class WooContentProcessorTest extends \WC_Unit_Test_Case {
\WC_Emails::instance()->init();
}
+ /**
+ * @testdox Should strip typography properties from WooCommerce CSS.
+ */
+ public function test_prepare_css_strips_typography_properties(): void {
+ $css = 'h2 { color: red; font-family: Arial; font-size: 20px; font-weight: bold; line-height: 1.5; letter-spacing: -1px; margin: 0; }';
+
+ $result = $this->woo_content_processor->prepare_css( $css );
+
+ $this->assertStringNotContainsString( 'color', $result, 'Color should be stripped' );
+ $this->assertStringNotContainsString( 'font-family', $result, 'Font-family should be stripped' );
+ $this->assertStringNotContainsString( 'font-size', $result, 'Font-size should be stripped' );
+ $this->assertStringNotContainsString( 'font-weight', $result, 'Font-weight should be stripped' );
+ $this->assertStringNotContainsString( 'line-height', $result, 'Line-height should be stripped' );
+ $this->assertStringNotContainsString( 'letter-spacing', $result, 'Letter-spacing should be stripped' );
+ $this->assertStringContainsString( 'margin', $result, 'Non-typography properties should be preserved' );
+ }
+
+ /**
+ * @testdox Should return WooCommerce content styles with correct order totals CSS.
+ */
+ public function test_get_woo_content_styles_contains_order_totals_css(): void {
+ $reflection = new \ReflectionClass( $this->woo_content_processor );
+ $method = $reflection->getMethod( 'get_woo_content_styles' );
+ $method->setAccessible( true );
+
+ $css = $method->invoke( $this->woo_content_processor );
+
+ $this->assertStringContainsString( '.order-totals th', $css, 'Should target order totals headers' );
+ $this->assertStringContainsString( '.order-totals-total th', $css, 'Should target total row header' );
+ $this->assertStringContainsString( '.order-totals-total td', $css, 'Should target total row value' );
+ $this->assertStringContainsString( 'font-weight: 400', $css, 'Non-total rows should be regular weight' );
+ $this->assertStringContainsString( 'font-weight: 700', $css, 'Total row should be bold' );
+ $this->assertStringContainsString( 'font-size: 20px', $css, 'Total value should be 20px' );
+ $this->assertStringContainsString( '.email-order-item-meta', $css, 'Should target order item metadata' );
+ $this->assertStringContainsString( 'h2.email-order-detail-heading', $css, 'Should target section headings' );
+ }
+
/**
* Test that the BlockEmailRenderer can render email and replaces Woo Content.
*/