From 6bfeefa6362114418a9ea93529914428bd23f473 Mon Sep 17 00:00:00 2001 From: Amit Raj Date: Tue, 8 Sep 2026 05:47:13 +0530 Subject: [PATCH 01/12] Media & Text: replace deprecated word-break with overflow-wrap: anywhere --- packages/block-library/src/media-text/style.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/media-text/style.scss b/packages/block-library/src/media-text/style.scss index 3a9d4256c738b1..70f1559ab2d6f8 100644 --- a/packages/block-library/src/media-text/style.scss +++ b/packages/block-library/src/media-text/style.scss @@ -52,8 +52,8 @@ grid-column: 2; grid-row: 1; /*rtl:end:ignore*/ - // stylelint-disable-next-line declaration-property-value-keyword-no-deprecated -- Pending review of overflow-wrap alternative. - word-break: break-word; + word-break: normal; + overflow-wrap: anywhere; } // Zero specificity so the default padding can be overridden by theme.json or theme styles. From 3c66a8198589e1d8135b764fa54f16969797fbea Mon Sep 17 00:00:00 2001 From: Shail Mehta Date: Wed, 23 Sep 2026 20:55:07 +0530 Subject: [PATCH 02/12] Apply Feedback Changes --- .../block-library/src/media-text/editor.scss | 11 +++ packages/block-library/src/search/style.scss | 3 + .../specs/editor/blocks/media-text.spec.js | 67 +++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 test/e2e/specs/editor/blocks/media-text.spec.js diff --git a/packages/block-library/src/media-text/editor.scss b/packages/block-library/src/media-text/editor.scss index 83a010e3bc45b4..7bf153ab248ef2 100644 --- a/packages/block-library/src/media-text/editor.scss +++ b/packages/block-library/src/media-text/editor.scss @@ -39,6 +39,17 @@ max-width: unset; } +.wp-block-media-text__content { + // The UA stylesheet sets `overflow-wrap: break-word` on editable + // elements, which would otherwise win over the inherited `anywhere` + // from style.scss and inflate the content column's min-content size. + // Exclude Search's button: it opts out of wrapping and must keep + // `overflow-wrap: normal` (see search/style.scss). + [contenteditable="true"]:not(.wp-block-search__button) { + overflow-wrap: inherit; + } +} + /* Make the featured image placeholder the same height as the media selection area. */ .wp-block-media-text--placeholder-image { min-height: 205px; diff --git a/packages/block-library/src/search/style.scss b/packages/block-library/src/search/style.scss index a39a5ceb335624..645c33ff6f34d3 100644 --- a/packages/block-library/src/search/style.scss +++ b/packages/block-library/src/search/style.scss @@ -7,7 +7,10 @@ $button-spacing-y: math.div($grid-unit-15, 2); // 6px .wp-block-search__button { margin-left: $button-spacing-x; + // Opt out of wrapping: pair both properties so an ancestor's + // `overflow-wrap: anywhere` (e.g. Media & Text) cannot force wraps. word-break: normal; + overflow-wrap: normal; &.has-icon { line-height: 0; diff --git a/test/e2e/specs/editor/blocks/media-text.spec.js b/test/e2e/specs/editor/blocks/media-text.spec.js new file mode 100644 index 00000000000000..00075cccea1d49 --- /dev/null +++ b/test/e2e/specs/editor/blocks/media-text.spec.js @@ -0,0 +1,67 @@ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +// 50 characters with no spaces — long enough to wrap if overflow-wrap is anywhere. +const LONG_BUTTON_LABEL = 'A'.repeat( 50 ); + +test.describe( 'Media & Text', () => { + test.beforeEach( async ( { admin } ) => { + await admin.createNewPost(); + } ); + + test( 'should keep a nested Search button with a long custom label on one line', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/media-text', + attributes: { + mediaType: 'image', + mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg', + }, + innerBlocks: [ + { + name: 'core/search', + attributes: { + label: 'Search', + showLabel: false, + buttonUseIcon: false, + buttonPosition: 'button-outside', + buttonText: LONG_BUTTON_LABEL, + }, + }, + ], + } ); + + const postId = await editor.publishPost(); + await page.goto( `/?p=${ postId }` ); + + const button = page.locator( + '.wp-block-media-text__content .wp-block-search__button' + ); + await expect( button ).toBeVisible(); + await expect( button ).toHaveCSS( 'overflow-wrap', 'normal' ); + + // Wrapped labels roughly double the button height (ciampo: ~31px → ~46px). + await expect + .poll( async () => { + return button.evaluate( ( el ) => { + const { + paddingTop, + paddingBottom, + borderTopWidth, + borderBottomWidth, + lineHeight, + } = getComputedStyle( el ); + const verticalChrome = + parseFloat( paddingTop ) + + parseFloat( paddingBottom ) + + parseFloat( borderTopWidth ) + + parseFloat( borderBottomWidth ); + const singleLineHeight = + parseFloat( lineHeight ) + verticalChrome; + return el.getBoundingClientRect().height / singleLineHeight; + } ); + } ) + .toBeLessThan( 1.35 ); + } ); +} ); From 2fd0a6e56173b54ad12ab91c3f57ac373688a501 Mon Sep 17 00:00:00 2001 From: Shail Mehta Date: Wed, 23 Sep 2026 21:11:33 +0530 Subject: [PATCH 03/12] fix lint issue in test --- test/e2e/specs/editor/blocks/media-text.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/specs/editor/blocks/media-text.spec.js b/test/e2e/specs/editor/blocks/media-text.spec.js index 00075cccea1d49..a79b37575f69d3 100644 --- a/test/e2e/specs/editor/blocks/media-text.spec.js +++ b/test/e2e/specs/editor/blocks/media-text.spec.js @@ -51,7 +51,7 @@ test.describe( 'Media & Text', () => { borderTopWidth, borderBottomWidth, lineHeight, - } = getComputedStyle( el ); + } = window.getComputedStyle( el ); const verticalChrome = parseFloat( paddingTop ) + parseFloat( paddingBottom ) + From fd29714fd3e49a3eef6c1214746681ebe2807071 Mon Sep 17 00:00:00 2001 From: Shail Mehta Date: Wed, 30 Sep 2026 19:51:23 +0530 Subject: [PATCH 04/12] Apply Feedback changes --- .../block-library/src/media-text/editor.scss | 17 ++++--- .../block-library/src/media-text/style.scss | 9 ++++ .../specs/editor/blocks/media-text.spec.js | 44 +++++++++++++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/media-text/editor.scss b/packages/block-library/src/media-text/editor.scss index 7bf153ab248ef2..7d1194b645decc 100644 --- a/packages/block-library/src/media-text/editor.scss +++ b/packages/block-library/src/media-text/editor.scss @@ -39,14 +39,17 @@ max-width: unset; } -.wp-block-media-text__content { - // The UA stylesheet sets `overflow-wrap: break-word` on editable - // elements, which would otherwise win over the inherited `anywhere` - // from style.scss and inflate the content column's min-content size. - // Exclude Search's button: it opts out of wrapping and must keep - // `overflow-wrap: normal` (see search/style.scss). +.wp-block-media-text .wp-block-media-text__content { + // The block list and UA stylesheet set `overflow-wrap: break-word` on + // block wrappers / editable elements. That wins over the inherited + // `anywhere` from style.scss and inflates the content column's + // min-content size (horizontal editor scroll). Re-assert anywhere + // with enough specificity to beat `.block-editor-block-list__layout + // .block-editor-block-list__block`. Exclude Search's button: it opts + // out of wrapping (see search/style.scss). + .block-editor-block-list__block, [contenteditable="true"]:not(.wp-block-search__button) { - overflow-wrap: inherit; + overflow-wrap: anywhere; } } diff --git a/packages/block-library/src/media-text/style.scss b/packages/block-library/src/media-text/style.scss index 70f1559ab2d6f8..bf0602c7013acd 100644 --- a/packages/block-library/src/media-text/style.scss +++ b/packages/block-library/src/media-text/style.scss @@ -54,6 +54,15 @@ /*rtl:end:ignore*/ word-break: normal; overflow-wrap: anywhere; + + // Quote, Pullquote and Code set overflow-wrap: break-word. That overrides + // the inherited anywhere and lets long unbroken text inflate the content + // column's min-content size (horizontal page scroll). + .wp-block-quote, + .wp-block-pullquote, + .wp-block-code code { + overflow-wrap: anywhere; + } } // Zero specificity so the default padding can be overridden by theme.json or theme styles. diff --git a/test/e2e/specs/editor/blocks/media-text.spec.js b/test/e2e/specs/editor/blocks/media-text.spec.js index a79b37575f69d3..0eff297821299f 100644 --- a/test/e2e/specs/editor/blocks/media-text.spec.js +++ b/test/e2e/specs/editor/blocks/media-text.spec.js @@ -2,6 +2,8 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); // 50 characters with no spaces — long enough to wrap if overflow-wrap is anywhere. const LONG_BUTTON_LABEL = 'A'.repeat( 50 ); +// Long enough to inflate the Media & Text content column without mid-word wrapping. +const LONG_UNBROKEN_TEXT = 'A'.repeat( 200 ); test.describe( 'Media & Text', () => { test.beforeEach( async ( { admin } ) => { @@ -64,4 +66,46 @@ test.describe( 'Media & Text', () => { } ) .toBeLessThan( 1.35 ); } ); + + test( 'should keep nested Quote wrapping so the page does not scroll horizontally', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/media-text', + attributes: { + mediaType: 'image', + mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg', + }, + innerBlocks: [ + { + name: 'core/quote', + innerBlocks: [ + { + name: 'core/paragraph', + attributes: { content: LONG_UNBROKEN_TEXT }, + }, + ], + }, + ], + } ); + + const postId = await editor.publishPost(); + await page.goto( `/?p=${ postId }` ); + + const quote = page.locator( + '.wp-block-media-text__content .wp-block-quote' + ); + await expect( quote ).toBeVisible(); + await expect( quote ).toHaveCSS( 'overflow-wrap', 'anywhere' ); + + await expect + .poll( async () => { + return page.evaluate( () => { + const root = document.documentElement; + return root.scrollWidth - root.clientWidth; + } ); + } ) + .toBeLessThanOrEqual( 1 ); + } ); } ); From bf2e5f1537d8e6eda5f91f7fdd284d0d9dfc7e4c Mon Sep 17 00:00:00 2001 From: Shail Mehta Date: Sat, 3 Oct 2026 19:20:59 +0530 Subject: [PATCH 05/12] Apply Feedback Changes --- .../block-library/src/media-text/style.scss | 13 +- .../specs/editor/blocks/media-text.spec.js | 169 +++++++++++++++--- 2 files changed, 156 insertions(+), 26 deletions(-) diff --git a/packages/block-library/src/media-text/style.scss b/packages/block-library/src/media-text/style.scss index bf0602c7013acd..e5559e089af5aa 100644 --- a/packages/block-library/src/media-text/style.scss +++ b/packages/block-library/src/media-text/style.scss @@ -55,12 +55,13 @@ word-break: normal; overflow-wrap: anywhere; - // Quote, Pullquote and Code set overflow-wrap: break-word. That overrides - // the inherited anywhere and lets long unbroken text inflate the content - // column's min-content size (horizontal page scroll). - .wp-block-quote, - .wp-block-pullquote, - .wp-block-code code { + // Nested blocks that set overflow-wrap: break-word (Quote, Pullquote, Code, + // Embed, Latest Posts, Author Biography, Verse, Columns, …) override the + // inherited anywhere and let long unbroken text inflate the content + // column's min-content size (horizontal page scroll). Re-assert anywhere on + // all descendants; Search's button opts out via + // `.wp-block-search__button { overflow-wrap: normal }`. + *:not(.wp-block-search__button) { overflow-wrap: anywhere; } } diff --git a/test/e2e/specs/editor/blocks/media-text.spec.js b/test/e2e/specs/editor/blocks/media-text.spec.js index 0eff297821299f..ebb5aaf4c8095d 100644 --- a/test/e2e/specs/editor/blocks/media-text.spec.js +++ b/test/e2e/specs/editor/blocks/media-text.spec.js @@ -5,6 +5,17 @@ const LONG_BUTTON_LABEL = 'A'.repeat( 50 ); // Long enough to inflate the Media & Text content column without mid-word wrapping. const LONG_UNBROKEN_TEXT = 'A'.repeat( 200 ); +async function expectNoHorizontalPageScroll( page ) { + await expect + .poll( async () => { + return page.evaluate( () => { + const root = document.documentElement; + return root.scrollWidth - root.clientWidth; + } ); + } ) + .toBeLessThanOrEqual( 1 ); +} + test.describe( 'Media & Text', () => { test.beforeEach( async ( { admin } ) => { await admin.createNewPost(); @@ -67,10 +78,89 @@ test.describe( 'Media & Text', () => { .toBeLessThan( 1.35 ); } ); - test( 'should keep nested Quote wrapping so the page does not scroll horizontally', async ( { + const nestedWrappingCases = [ + { + name: 'Quote', + selector: '.wp-block-media-text__content .wp-block-quote', + innerBlocks: [ + { + name: 'core/quote', + innerBlocks: [ + { + name: 'core/paragraph', + attributes: { content: LONG_UNBROKEN_TEXT }, + }, + ], + }, + ], + }, + { + name: 'Embed caption', + selector: '.wp-block-media-text__content .wp-block-embed', + innerBlocks: [ + { + name: 'core/embed', + attributes: { + url: 'https://wordpress.org/gutenberg', + caption: LONG_UNBROKEN_TEXT, + }, + }, + ], + }, + { + name: 'Verse', + selector: '.wp-block-media-text__content .wp-block-verse', + innerBlocks: [ + { + name: 'core/verse', + attributes: { content: LONG_UNBROKEN_TEXT }, + }, + ], + }, + ]; + + for ( const wrappingCase of nestedWrappingCases ) { + test( `should keep nested ${ wrappingCase.name } wrapping so the page does not scroll horizontally`, async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/media-text', + attributes: { + mediaType: 'image', + mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg', + }, + innerBlocks: wrappingCase.innerBlocks, + } ); + + const postId = await editor.publishPost(); + await page.goto( `/?p=${ postId }` ); + + const nested = page.locator( wrappingCase.selector ); + await expect( nested.first() ).toBeVisible(); + await expect( nested.first() ).toHaveCSS( + 'overflow-wrap', + 'anywhere' + ); + await expectNoHorizontalPageScroll( page ); + } ); + } + + test( 'should keep nested Latest Posts titles wrapping so the page does not scroll horizontally', async ( { editor, page, + requestUtils, } ) => { + await requestUtils.rest( { + method: 'POST', + path: '/wp/v2/posts', + data: { + title: LONG_UNBROKEN_TEXT, + status: 'publish', + content: 'Latest Posts overflow-wrap fixture.', + }, + } ); + await editor.insertBlock( { name: 'core/media-text', attributes: { @@ -79,13 +169,11 @@ test.describe( 'Media & Text', () => { }, innerBlocks: [ { - name: 'core/quote', - innerBlocks: [ - { - name: 'core/paragraph', - attributes: { content: LONG_UNBROKEN_TEXT }, - }, - ], + name: 'core/latest-posts', + attributes: { + postsToShow: 1, + displayPostContent: false, + }, }, ], } ); @@ -93,19 +181,60 @@ test.describe( 'Media & Text', () => { const postId = await editor.publishPost(); await page.goto( `/?p=${ postId }` ); - const quote = page.locator( - '.wp-block-media-text__content .wp-block-quote' + const latestPostsItem = page.locator( + '.wp-block-media-text__content .wp-block-latest-posts li' + ); + await expect( latestPostsItem.first() ).toBeVisible(); + await expect( latestPostsItem.first() ).toHaveCSS( + 'overflow-wrap', + 'anywhere' ); - await expect( quote ).toBeVisible(); - await expect( quote ).toHaveCSS( 'overflow-wrap', 'anywhere' ); + await expectNoHorizontalPageScroll( page ); + } ); - await expect - .poll( async () => { - return page.evaluate( () => { - const root = document.documentElement; - return root.scrollWidth - root.clientWidth; - } ); - } ) - .toBeLessThanOrEqual( 1 ); + test( 'should keep nested Author Biography wrapping so the page does not scroll horizontally', async ( { + editor, + page, + requestUtils, + } ) => { + const me = await requestUtils.rest( { + method: 'GET', + path: '/wp/v2/users/me', + params: { context: 'edit' }, + } ); + const previousDescription = me.description ?? ''; + + await requestUtils.rest( { + method: 'POST', + path: '/wp/v2/users/me', + data: { description: LONG_UNBROKEN_TEXT }, + } ); + + try { + await editor.insertBlock( { + name: 'core/media-text', + attributes: { + mediaType: 'image', + mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg', + }, + innerBlocks: [ { name: 'core/post-author-biography' } ], + } ); + + const postId = await editor.publishPost(); + await page.goto( `/?p=${ postId }` ); + + const biography = page.locator( + '.wp-block-media-text__content .wp-block-post-author-biography' + ); + await expect( biography ).toBeVisible(); + await expect( biography ).toHaveCSS( 'overflow-wrap', 'anywhere' ); + await expectNoHorizontalPageScroll( page ); + } finally { + await requestUtils.rest( { + method: 'POST', + path: '/wp/v2/users/me', + data: { description: previousDescription }, + } ); + } } ); } ); From 9d056495226db2d8c72d06d4d1ac16f5938c17f7 Mon Sep 17 00:00:00 2001 From: Shail Mehta Date: Sat, 3 Oct 2026 19:48:36 +0530 Subject: [PATCH 06/12] fix test --- .../specs/editor/blocks/media-text.spec.js | 87 +++++++++++++------ 1 file changed, 59 insertions(+), 28 deletions(-) diff --git a/test/e2e/specs/editor/blocks/media-text.spec.js b/test/e2e/specs/editor/blocks/media-text.spec.js index ebb5aaf4c8095d..46f2cb0922dfd7 100644 --- a/test/e2e/specs/editor/blocks/media-text.spec.js +++ b/test/e2e/specs/editor/blocks/media-text.spec.js @@ -16,6 +16,25 @@ async function expectNoHorizontalPageScroll( page ) { .toBeLessThanOrEqual( 1 ); } +// When the long string also appears in theme chrome (adjacent post nav, author +// bio outside the block), page scrollWidth is not a reliable signal. Assert the +// Media & Text block itself stays within the viewport instead. +async function expectMediaTextFitsViewport( page ) { + await expect + .poll( async () => { + return page.evaluate( () => { + const mediaText = document.querySelector( + '.wp-block-media-text' + ); + const root = document.documentElement; + return ( + mediaText.getBoundingClientRect().width - root.clientWidth + ); + } ); + } ) + .toBeLessThanOrEqual( 1 ); +} + test.describe( 'Media & Text', () => { test.beforeEach( async ( { admin } ) => { await admin.createNewPost(); @@ -151,7 +170,7 @@ test.describe( 'Media & Text', () => { page, requestUtils, } ) => { - await requestUtils.rest( { + const fixturePost = await requestUtils.rest( { method: 'POST', path: '/wp/v2/posts', data: { @@ -161,35 +180,45 @@ test.describe( 'Media & Text', () => { }, } ); - await editor.insertBlock( { - name: 'core/media-text', - attributes: { - mediaType: 'image', - mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg', - }, - innerBlocks: [ - { - name: 'core/latest-posts', - attributes: { - postsToShow: 1, - displayPostContent: false, - }, + try { + await editor.insertBlock( { + name: 'core/media-text', + attributes: { + mediaType: 'image', + mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg', }, - ], - } ); + innerBlocks: [ + { + name: 'core/latest-posts', + attributes: { + postsToShow: 1, + displayPostContent: false, + }, + }, + ], + } ); - const postId = await editor.publishPost(); - await page.goto( `/?p=${ postId }` ); + const postId = await editor.publishPost(); + await page.goto( `/?p=${ postId }` ); - const latestPostsItem = page.locator( - '.wp-block-media-text__content .wp-block-latest-posts li' - ); - await expect( latestPostsItem.first() ).toBeVisible(); - await expect( latestPostsItem.first() ).toHaveCSS( - 'overflow-wrap', - 'anywhere' - ); - await expectNoHorizontalPageScroll( page ); + const latestPostsItem = page.locator( + '.wp-block-media-text__content .wp-block-latest-posts li' + ); + await expect( latestPostsItem.first() ).toBeVisible(); + await expect( latestPostsItem.first() ).toHaveCSS( + 'overflow-wrap', + 'anywhere' + ); + // Long titles can also appear in theme post navigation outside the + // block, so assert on Media & Text fitting the viewport. + await expectMediaTextFitsViewport( page ); + } finally { + await requestUtils.rest( { + method: 'DELETE', + path: `/wp/v2/posts/${ fixturePost.id }`, + params: { force: true }, + } ); + } } ); test( 'should keep nested Author Biography wrapping so the page does not scroll horizontally', async ( { @@ -228,7 +257,9 @@ test.describe( 'Media & Text', () => { ); await expect( biography ).toBeVisible(); await expect( biography ).toHaveCSS( 'overflow-wrap', 'anywhere' ); - await expectNoHorizontalPageScroll( page ); + // The same bio can render in theme chrome outside Media & Text, so + // assert on the block fitting the viewport rather than page scroll. + await expectMediaTextFitsViewport( page ); } finally { await requestUtils.rest( { method: 'POST', From a68ca8a474efd0a7200c8fc895b40db5b8d20669 Mon Sep 17 00:00:00 2001 From: Shail Mehta Date: Thu, 8 Oct 2026 19:47:00 +0530 Subject: [PATCH 07/12] Apply Feedback changes --- .../block-library/src/media-text/editor.scss | 9 +- .../block-library/src/media-text/style.scss | 9 +- .../specs/editor/blocks/media-text.spec.js | 127 ++++++++++-------- 3 files changed, 88 insertions(+), 57 deletions(-) diff --git a/packages/block-library/src/media-text/editor.scss b/packages/block-library/src/media-text/editor.scss index 7d1194b645decc..fa0d5bcd2a97f6 100644 --- a/packages/block-library/src/media-text/editor.scss +++ b/packages/block-library/src/media-text/editor.scss @@ -45,12 +45,17 @@ // `anywhere` from style.scss and inflates the content column's // min-content size (horizontal editor scroll). Re-assert anywhere // with enough specificity to beat `.block-editor-block-list__layout - // .block-editor-block-list__block`. Exclude Search's button: it opts - // out of wrapping (see search/style.scss). + // .block-editor-block-list__block`. Exclude Search's button and its + // formatted label: they opt out of wrapping (see search/style.scss). .block-editor-block-list__block, [contenteditable="true"]:not(.wp-block-search__button) { overflow-wrap: anywhere; } + + .wp-block-search__button, + .wp-block-search__button * { + overflow-wrap: normal; + } } /* Make the featured image placeholder the same height as the media selection area. */ diff --git a/packages/block-library/src/media-text/style.scss b/packages/block-library/src/media-text/style.scss index e5559e089af5aa..5f3190416c4259 100644 --- a/packages/block-library/src/media-text/style.scss +++ b/packages/block-library/src/media-text/style.scss @@ -59,11 +59,16 @@ // Embed, Latest Posts, Author Biography, Verse, Columns, …) override the // inherited anywhere and let long unbroken text inflate the content // column's min-content size (horizontal page scroll). Re-assert anywhere on - // all descendants; Search's button opts out via - // `.wp-block-search__button { overflow-wrap: normal }`. + // all descendants; Search's button and its formatted label (e.g. strong/em) + // opt out via search/style.scss and the override below. *:not(.wp-block-search__button) { overflow-wrap: anywhere; } + + .wp-block-search__button, + .wp-block-search__button * { + overflow-wrap: normal; + } } // Zero specificity so the default padding can be overridden by theme.json or theme styles. diff --git a/test/e2e/specs/editor/blocks/media-text.spec.js b/test/e2e/specs/editor/blocks/media-text.spec.js index 46f2cb0922dfd7..401d69a0ad6c49 100644 --- a/test/e2e/specs/editor/blocks/media-text.spec.js +++ b/test/e2e/specs/editor/blocks/media-text.spec.js @@ -19,6 +19,43 @@ async function expectNoHorizontalPageScroll( page ) { // When the long string also appears in theme chrome (adjacent post nav, author // bio outside the block), page scrollWidth is not a reliable signal. Assert the // Media & Text block itself stays within the viewport instead. +async function expectNestedSearchButtonLabelSingleLine( page, buttonText ) { + const button = page.locator( + '.wp-block-media-text__content .wp-block-search__button' + ); + await expect( button ).toBeVisible(); + await expect( button ).toHaveCSS( 'overflow-wrap', 'normal' ); + + if ( buttonText.includes( '' ) || buttonText.includes( '' ) ) { + const formattedLabel = button.locator( 'strong, em' ).first(); + await expect( formattedLabel ).toBeVisible(); + await expect( formattedLabel ).toHaveCSS( 'overflow-wrap', 'normal' ); + } + + // Wrapped labels roughly double the button height (ciampo: ~31px → ~46px). + await expect + .poll( async () => { + return button.evaluate( ( el ) => { + const { + paddingTop, + paddingBottom, + borderTopWidth, + borderBottomWidth, + lineHeight, + } = window.getComputedStyle( el ); + const verticalChrome = + parseFloat( paddingTop ) + + parseFloat( paddingBottom ) + + parseFloat( borderTopWidth ) + + parseFloat( borderBottomWidth ); + const singleLineHeight = + parseFloat( lineHeight ) + verticalChrome; + return el.getBoundingClientRect().height / singleLineHeight; + } ); + } ) + .toBeLessThan( 1.35 ); +} + async function expectMediaTextFitsViewport( page ) { await expect .poll( async () => { @@ -40,62 +77,46 @@ test.describe( 'Media & Text', () => { await admin.createNewPost(); } ); - test( 'should keep a nested Search button with a long custom label on one line', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { - name: 'core/media-text', - attributes: { - mediaType: 'image', - mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg', - }, - innerBlocks: [ - { - name: 'core/search', - attributes: { - label: 'Search', - showLabel: false, - buttonUseIcon: false, - buttonPosition: 'button-outside', - buttonText: LONG_BUTTON_LABEL, - }, + for ( const { description, buttonText } of [ + { + description: 'plain', + buttonText: LONG_BUTTON_LABEL, + }, + { + description: 'bold', + buttonText: `${ LONG_BUTTON_LABEL }`, + }, + ] ) { + test( `should keep a nested Search button with a long custom ${ description } label on one line`, async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/media-text', + attributes: { + mediaType: 'image', + mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg', }, - ], - } ); - - const postId = await editor.publishPost(); - await page.goto( `/?p=${ postId }` ); + innerBlocks: [ + { + name: 'core/search', + attributes: { + label: 'Search', + showLabel: false, + buttonUseIcon: false, + buttonPosition: 'button-outside', + buttonText, + }, + }, + ], + } ); - const button = page.locator( - '.wp-block-media-text__content .wp-block-search__button' - ); - await expect( button ).toBeVisible(); - await expect( button ).toHaveCSS( 'overflow-wrap', 'normal' ); + const postId = await editor.publishPost(); + await page.goto( `/?p=${ postId }` ); - // Wrapped labels roughly double the button height (ciampo: ~31px → ~46px). - await expect - .poll( async () => { - return button.evaluate( ( el ) => { - const { - paddingTop, - paddingBottom, - borderTopWidth, - borderBottomWidth, - lineHeight, - } = window.getComputedStyle( el ); - const verticalChrome = - parseFloat( paddingTop ) + - parseFloat( paddingBottom ) + - parseFloat( borderTopWidth ) + - parseFloat( borderBottomWidth ); - const singleLineHeight = - parseFloat( lineHeight ) + verticalChrome; - return el.getBoundingClientRect().height / singleLineHeight; - } ); - } ) - .toBeLessThan( 1.35 ); - } ); + await expectNestedSearchButtonLabelSingleLine( page, buttonText ); + } ); + } const nestedWrappingCases = [ { From b705c3e25e231431ccb20398795854bc1ab5b8fc Mon Sep 17 00:00:00 2001 From: Shail Mehta Date: Fri, 9 Oct 2026 21:10:48 +0530 Subject: [PATCH 08/12] Apply Feedback Changes --- .../block-library/src/media-text/editor.scss | 16 +- .../block-library/src/media-text/style.scss | 45 ++++- .../specs/editor/blocks/media-text.spec.js | 186 +++++++++++++++--- 3 files changed, 202 insertions(+), 45 deletions(-) diff --git a/packages/block-library/src/media-text/editor.scss b/packages/block-library/src/media-text/editor.scss index fa0d5bcd2a97f6..4b5e60fd5787d2 100644 --- a/packages/block-library/src/media-text/editor.scss +++ b/packages/block-library/src/media-text/editor.scss @@ -43,18 +43,14 @@ // The block list and UA stylesheet set `overflow-wrap: break-word` on // block wrappers / editable elements. That wins over the inherited // `anywhere` from style.scss and inflates the content column's - // min-content size (horizontal editor scroll). Re-assert anywhere - // with enough specificity to beat `.block-editor-block-list__layout - // .block-editor-block-list__block`. Exclude Search's button and its - // formatted label: they opt out of wrapping (see search/style.scss). + // min-content size (horizontal editor scroll). Inherit from the content + // column with enough specificity to beat + // `.block-editor-block-list__layout .block-editor-block-list__block`. + // Nested blocks that set break-word are re-asserted in style.scss. + // Exclude Search's button: it opts out via search/style.scss. .block-editor-block-list__block, [contenteditable="true"]:not(.wp-block-search__button) { - overflow-wrap: anywhere; - } - - .wp-block-search__button, - .wp-block-search__button * { - overflow-wrap: normal; + overflow-wrap: inherit; } } diff --git a/packages/block-library/src/media-text/style.scss b/packages/block-library/src/media-text/style.scss index 5f3190416c4259..e8ac914d296d07 100644 --- a/packages/block-library/src/media-text/style.scss +++ b/packages/block-library/src/media-text/style.scss @@ -55,19 +55,44 @@ word-break: normal; overflow-wrap: anywhere; - // Nested blocks that set overflow-wrap: break-word (Quote, Pullquote, Code, - // Embed, Latest Posts, Author Biography, Verse, Columns, …) override the - // inherited anywhere and let long unbroken text inflate the content - // column's min-content size (horizontal page scroll). Re-assert anywhere on - // all descendants; Search's button and its formatted label (e.g. strong/em) - // opt out via search/style.scss and the override below. - *:not(.wp-block-search__button) { + // Nested blocks that set overflow-wrap: break-word (or sit under theme + // rules like `.entry-content p { overflow-wrap: break-word }`) override + // the inherited anywhere and let long unbroken text inflate the content + // column's min-content size. Re-assert anywhere on those blocks and their + // descendants only — a content-wide `*` catch-all would also override + // intentional opt-outs such as a custom `.no-break { overflow-wrap: normal }`. + // Search's button opts out via search/style.scss and is not listed here. + .wp-block-quote, + .wp-block-quote *, + .wp-block-pullquote, + .wp-block-pullquote *, + .wp-block-embed, + .wp-block-embed *, + .wp-block-verse, + .wp-block-verse *, + .wp-block-column, + .wp-block-column *, + .wp-block-post-author-biography, + .wp-block-post-author-biography *, + .wp-block-latest-posts li, + .wp-block-latest-posts li *, + .wp-block-navigation-item__label, + .wp-block-navigation-item__label *, + .wp-block-post-comments-form input[type="submit"] { overflow-wrap: anywhere; } - .wp-block-search__button, - .wp-block-search__button * { - overflow-wrap: normal; + // Code is a
; the UA white-space: pre ignores overflow-wrap, so the
+	// long unbroken string still inflates min-content unless the pre itself
+	// is allowed to wrap. min-width: 0 lets the grid track shrink.
+	.wp-block-code {
+		overflow-wrap: anywhere;
+		white-space: break-spaces;
+		min-width: 0;
+
+		code {
+			overflow-wrap: anywhere;
+		}
 	}
 }
 
diff --git a/test/e2e/specs/editor/blocks/media-text.spec.js b/test/e2e/specs/editor/blocks/media-text.spec.js
index 401d69a0ad6c49..fcd69c7d9ee44c 100644
--- a/test/e2e/specs/editor/blocks/media-text.spec.js
+++ b/test/e2e/specs/editor/blocks/media-text.spec.js
@@ -4,6 +4,8 @@ const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );
 const LONG_BUTTON_LABEL = 'A'.repeat( 50 );
 // Long enough to inflate the Media & Text content column without mid-word wrapping.
 const LONG_UNBROKEN_TEXT = 'A'.repeat( 200 );
+// Shorter string for the custom opt-out height check (matches ciampo's reproduction).
+const OPT_OUT_UNBROKEN_TEXT = 'A'.repeat( 50 );
 
 async function expectNoHorizontalPageScroll( page ) {
 	await expect
@@ -18,7 +20,20 @@ async function expectNoHorizontalPageScroll( page ) {
 
 // When the long string also appears in theme chrome (adjacent post nav, author
 // bio outside the block), page scrollWidth is not a reliable signal. Assert the
-// Media & Text block itself stays within the viewport instead.
+// Media & Text block itself does not overflow its client box.
+async function expectMediaTextContentFits( page ) {
+	await expect
+		.poll( async () => {
+			return page.evaluate( () => {
+				const mediaText = document.querySelector(
+					'.wp-block-media-text'
+				);
+				return mediaText.scrollWidth - mediaText.clientWidth;
+			} );
+		} )
+		.toBeLessThanOrEqual( 1 );
+}
+
 async function expectNestedSearchButtonLabelSingleLine( page, buttonText ) {
 	const button = page.locator(
 		'.wp-block-media-text__content .wp-block-search__button'
@@ -33,6 +48,7 @@ async function expectNestedSearchButtonLabelSingleLine( page, buttonText ) {
 	}
 
 	// Wrapped labels roughly double the button height (ciampo: ~31px → ~46px).
+	// line-height may be `normal` (e.g. emptytheme), so fall back to font-size.
 	await expect
 		.poll( async () => {
 			return button.evaluate( ( el ) => {
@@ -42,41 +58,40 @@ async function expectNestedSearchButtonLabelSingleLine( page, buttonText ) {
 					borderTopWidth,
 					borderBottomWidth,
 					lineHeight,
+					fontSize,
 				} = window.getComputedStyle( el );
 				const verticalChrome =
 					parseFloat( paddingTop ) +
 					parseFloat( paddingBottom ) +
 					parseFloat( borderTopWidth ) +
 					parseFloat( borderBottomWidth );
-				const singleLineHeight =
-					parseFloat( lineHeight ) + verticalChrome;
+				const parsedLineHeight = parseFloat( lineHeight );
+				const resolvedLineHeight = Number.isFinite( parsedLineHeight )
+					? parsedLineHeight
+					: parseFloat( fontSize ) * 1.2;
+				const singleLineHeight = resolvedLineHeight + verticalChrome;
 				return el.getBoundingClientRect().height / singleLineHeight;
 			} );
 		} )
 		.toBeLessThan( 1.35 );
 }
 
-async function expectMediaTextFitsViewport( page ) {
-	await expect
-		.poll( async () => {
-			return page.evaluate( () => {
-				const mediaText = document.querySelector(
-					'.wp-block-media-text'
-				);
-				const root = document.documentElement;
-				return (
-					mediaText.getBoundingClientRect().width - root.clientWidth
-				);
-			} );
-		} )
-		.toBeLessThanOrEqual( 1 );
-}
-
 test.describe( 'Media & Text', () => {
+	// emptytheme has no `.entry-content p { overflow-wrap: break-word }`, so a
+	// custom `.no-break { overflow-wrap: normal }` opt-out can reach nested
+	// paragraphs via inheritance — matching ciampo's reproduction.
+	test.beforeAll( async ( { requestUtils } ) => {
+		await requestUtils.activateTheme( 'emptytheme' );
+	} );
+
 	test.beforeEach( async ( { admin } ) => {
 		await admin.createNewPost();
 	} );
 
+	test.afterAll( async ( { requestUtils } ) => {
+		await requestUtils.activateTheme( 'twentytwentyone' );
+	} );
+
 	for ( const { description, buttonText } of [
 		{
 			description: 'plain',
@@ -87,6 +102,7 @@ test.describe( 'Media & Text', () => {
 			buttonText: `${ LONG_BUTTON_LABEL }`,
 		},
 	] ) {
+		// eslint-disable-next-line playwright/expect-expect -- Asserted in the shared helper.
 		test( `should keep a nested Search button with a long custom ${ description } label on one line`, async ( {
 			editor,
 			page,
@@ -114,6 +130,7 @@ test.describe( 'Media & Text', () => {
 			const postId = await editor.publishPost();
 			await page.goto( `/?p=${ postId }` );
 
+			// Assertions live in the helper (overflow-wrap + single-line height).
 			await expectNestedSearchButtonLabelSingleLine( page, buttonText );
 		} );
 	}
@@ -134,6 +151,26 @@ test.describe( 'Media & Text', () => {
 				},
 			],
 		},
+		{
+			name: 'Pullquote',
+			selector: '.wp-block-media-text__content .wp-block-pullquote',
+			innerBlocks: [
+				{
+					name: 'core/pullquote',
+					attributes: { value: LONG_UNBROKEN_TEXT },
+				},
+			],
+		},
+		{
+			name: 'Code',
+			selector: '.wp-block-media-text__content .wp-block-code',
+			innerBlocks: [
+				{
+					name: 'core/code',
+					attributes: { content: LONG_UNBROKEN_TEXT },
+				},
+			],
+		},
 		{
 			name: 'Embed caption',
 			selector: '.wp-block-media-text__content .wp-block-embed',
@@ -157,6 +194,28 @@ test.describe( 'Media & Text', () => {
 				},
 			],
 		},
+		{
+			name: 'Column',
+			selector: '.wp-block-media-text__content .wp-block-column',
+			innerBlocks: [
+				{
+					name: 'core/columns',
+					innerBlocks: [
+						{
+							name: 'core/column',
+							innerBlocks: [
+								{
+									name: 'core/paragraph',
+									attributes: {
+										content: LONG_UNBROKEN_TEXT,
+									},
+								},
+							],
+						},
+					],
+				},
+			],
+		},
 	];
 
 	for ( const wrappingCase of nestedWrappingCases ) {
@@ -191,12 +250,21 @@ test.describe( 'Media & Text', () => {
 		page,
 		requestUtils,
 	} ) => {
+		const category = await requestUtils.rest( {
+			method: 'POST',
+			path: '/wp/v2/categories',
+			data: {
+				name: `Media Text Overflow ${ Date.now() }`,
+			},
+		} );
+
 		const fixturePost = await requestUtils.rest( {
 			method: 'POST',
 			path: '/wp/v2/posts',
 			data: {
 				title: LONG_UNBROKEN_TEXT,
 				status: 'publish',
+				categories: [ category.id ],
 				content: 'Latest Posts overflow-wrap fixture.',
 			},
 		} );
@@ -214,6 +282,7 @@ test.describe( 'Media & Text', () => {
 						attributes: {
 							postsToShow: 1,
 							displayPostContent: false,
+							categories: [ { id: category.id } ],
 						},
 					},
 				],
@@ -225,20 +294,26 @@ test.describe( 'Media & Text', () => {
 			const latestPostsItem = page.locator(
 				'.wp-block-media-text__content .wp-block-latest-posts li'
 			);
-			await expect( latestPostsItem.first() ).toBeVisible();
-			await expect( latestPostsItem.first() ).toHaveCSS(
+			await expect( latestPostsItem ).toHaveCount( 1 );
+			await expect( latestPostsItem ).toContainText( LONG_UNBROKEN_TEXT );
+			await expect( latestPostsItem ).toHaveCSS(
 				'overflow-wrap',
 				'anywhere'
 			);
 			// Long titles can also appear in theme post navigation outside the
-			// block, so assert on Media & Text fitting the viewport.
-			await expectMediaTextFitsViewport( page );
+			// block, so assert on Media & Text not overflowing its client box.
+			await expectMediaTextContentFits( page );
 		} finally {
 			await requestUtils.rest( {
 				method: 'DELETE',
 				path: `/wp/v2/posts/${ fixturePost.id }`,
 				params: { force: true },
 			} );
+			await requestUtils.rest( {
+				method: 'DELETE',
+				path: `/wp/v2/categories/${ category.id }`,
+				params: { force: true },
+			} );
 		}
 	} );
 
@@ -279,8 +354,8 @@ test.describe( 'Media & Text', () => {
 			await expect( biography ).toBeVisible();
 			await expect( biography ).toHaveCSS( 'overflow-wrap', 'anywhere' );
 			// The same bio can render in theme chrome outside Media & Text, so
-			// assert on the block fitting the viewport rather than page scroll.
-			await expectMediaTextFitsViewport( page );
+			// assert on the block not overflowing its client box.
+			await expectMediaTextContentFits( page );
 		} finally {
 			await requestUtils.rest( {
 				method: 'POST',
@@ -289,4 +364,65 @@ test.describe( 'Media & Text', () => {
 			} );
 		}
 	} );
+
+	test( 'should preserve a nested custom overflow-wrap: normal opt-out', async ( {
+		editor,
+		page,
+	} ) => {
+		await editor.insertBlock( {
+			name: 'core/media-text',
+			attributes: {
+				mediaType: 'image',
+				mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg',
+			},
+			innerBlocks: [
+				{
+					name: 'core/group',
+					attributes: {
+						className: 'no-break',
+					},
+					innerBlocks: [
+						{
+							name: 'core/paragraph',
+							attributes: { content: OPT_OUT_UNBROKEN_TEXT },
+						},
+					],
+				},
+			],
+		} );
+
+		const postId = await editor.publishPost();
+		await page.goto( `/?p=${ postId }` );
+
+		await page.addStyleTag( {
+			content: `
+				.no-break {
+					width: 220px;
+					word-break: normal;
+					overflow-wrap: normal;
+					font-family: Arial, sans-serif;
+					font-size: 16px;
+					line-height: 24px;
+				}
+			`,
+		} );
+
+		const optOut = page.locator(
+			'.wp-block-media-text__content .no-break'
+		);
+		await expect( optOut ).toBeVisible();
+		await expect( optOut ).toHaveCSS( 'overflow-wrap', 'normal' );
+
+		const paragraph = optOut.locator( 'p' ).first();
+		await expect( paragraph ).toHaveCSS( 'overflow-wrap', 'normal' );
+		// With overflow-wrap: normal the 50 A's stay on one line (~24px).
+		// anywhere would wrap them to multiple lines (~72px at 220px width).
+		await expect
+			.poll( async () => {
+				return paragraph.evaluate(
+					( el ) => el.getBoundingClientRect().height
+				);
+			} )
+			.toBeLessThanOrEqual( 30 );
+	} );
 } );

From 3a8ee2ada11056e1e20f9c48082e8e2c108d0814 Mon Sep 17 00:00:00 2001
From: Marco Ciampini 
Date: Mon, 12 Oct 2026 11:25:48 +0200
Subject: [PATCH 09/12] Media & Text: Preserve nested wrapping during
 overflow-wrap migration

---
 packages/block-library/CHANGELOG.md           |   1 +
 .../block-library/src/media-text/editor.scss  |  15 -
 .../block-library/src/media-text/style.scss   |  41 +-
 packages/block-library/src/search/style.scss  |   3 +-
 .../specs/editor/blocks/media-text.spec.js    | 469 ++++--------------
 5 files changed, 114 insertions(+), 415 deletions(-)

diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md
index 60f429e603c328..611ed06191ad8d 100644
--- a/packages/block-library/CHANGELOG.md
+++ b/packages/block-library/CHANGELOG.md
@@ -13,6 +13,7 @@
 
 ### Bug Fixes
 
+-   Media & Text: Replace deprecated `word-break: break-word` while keeping long content within the text column and preserving nested wrapping opt-outs ([#82580](https://github.com/WordPress/gutenberg/pull/82580)).
 -   Accordion Heading: Anchor notes to the selected title text instead of the whole block ([#84497](https://github.com/WordPress/gutenberg/pull/84497)).
 
 ## 11.2.0 (2026-10-07)
diff --git a/packages/block-library/src/media-text/editor.scss b/packages/block-library/src/media-text/editor.scss
index 4b5e60fd5787d2..83a010e3bc45b4 100644
--- a/packages/block-library/src/media-text/editor.scss
+++ b/packages/block-library/src/media-text/editor.scss
@@ -39,21 +39,6 @@
 	max-width: unset;
 }
 
-.wp-block-media-text .wp-block-media-text__content {
-	// The block list and UA stylesheet set `overflow-wrap: break-word` on
-	// block wrappers / editable elements. That wins over the inherited
-	// `anywhere` from style.scss and inflates the content column's
-	// min-content size (horizontal editor scroll). Inherit from the content
-	// column with enough specificity to beat
-	// `.block-editor-block-list__layout .block-editor-block-list__block`.
-	// Nested blocks that set break-word are re-asserted in style.scss.
-	// Exclude Search's button: it opts out via search/style.scss.
-	.block-editor-block-list__block,
-	[contenteditable="true"]:not(.wp-block-search__button) {
-		overflow-wrap: inherit;
-	}
-}
-
 /* Make the featured image placeholder the same height as the media selection area. */
 .wp-block-media-text--placeholder-image {
 	min-height: 205px;
diff --git a/packages/block-library/src/media-text/style.scss b/packages/block-library/src/media-text/style.scss
index e8ac914d296d07..b9c3217d70dc68 100644
--- a/packages/block-library/src/media-text/style.scss
+++ b/packages/block-library/src/media-text/style.scss
@@ -55,45 +55,8 @@
 	word-break: normal;
 	overflow-wrap: anywhere;
 
-	// Nested blocks that set overflow-wrap: break-word (or sit under theme
-	// rules like `.entry-content p { overflow-wrap: break-word }`) override
-	// the inherited anywhere and let long unbroken text inflate the content
-	// column's min-content size. Re-assert anywhere on those blocks and their
-	// descendants only — a content-wide `*` catch-all would also override
-	// intentional opt-outs such as a custom `.no-break { overflow-wrap: normal }`.
-	// Search's button opts out via search/style.scss and is not listed here.
-	.wp-block-quote,
-	.wp-block-quote *,
-	.wp-block-pullquote,
-	.wp-block-pullquote *,
-	.wp-block-embed,
-	.wp-block-embed *,
-	.wp-block-verse,
-	.wp-block-verse *,
-	.wp-block-column,
-	.wp-block-column *,
-	.wp-block-post-author-biography,
-	.wp-block-post-author-biography *,
-	.wp-block-latest-posts li,
-	.wp-block-latest-posts li *,
-	.wp-block-navigation-item__label,
-	.wp-block-navigation-item__label *,
-	.wp-block-post-comments-form input[type="submit"] {
-		overflow-wrap: anywhere;
-	}
-
-	// Code is a 
; the UA white-space: pre ignores overflow-wrap, so the
-	// long unbroken string still inflates min-content unless the pre itself
-	// is allowed to wrap. min-width: 0 lets the grid track shrink.
-	.wp-block-code {
-		overflow-wrap: anywhere;
-		white-space: break-spaces;
-		min-width: 0;
-
-		code {
-			overflow-wrap: anywhere;
-		}
-	}
+	// Let nested blocks wrap without expanding the grid track.
+	min-width: 0;
 }
 
 // Zero specificity so the default padding can be overridden by theme.json or theme styles.
diff --git a/packages/block-library/src/search/style.scss b/packages/block-library/src/search/style.scss
index 645c33ff6f34d3..2e16a5a085b2f5 100644
--- a/packages/block-library/src/search/style.scss
+++ b/packages/block-library/src/search/style.scss
@@ -7,8 +7,7 @@ $button-spacing-y: math.div($grid-unit-15, 2); // 6px
 
 .wp-block-search__button {
 	margin-left: $button-spacing-x;
-	// Opt out of wrapping: pair both properties so an ancestor's
-	// `overflow-wrap: anywhere` (e.g. Media & Text) cannot force wraps.
+	// Preserve the opt-out when an ancestor sets overflow-wrap.
 	word-break: normal;
 	overflow-wrap: normal;
 
diff --git a/test/e2e/specs/editor/blocks/media-text.spec.js b/test/e2e/specs/editor/blocks/media-text.spec.js
index fcd69c7d9ee44c..aa6d699b2ec4f7 100644
--- a/test/e2e/specs/editor/blocks/media-text.spec.js
+++ b/test/e2e/specs/editor/blocks/media-text.spec.js
@@ -1,202 +1,100 @@
 const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );
 
-// 50 characters with no spaces — long enough to wrap if overflow-wrap is anywhere.
-const LONG_BUTTON_LABEL = 'A'.repeat( 50 );
-// Long enough to inflate the Media & Text content column without mid-word wrapping.
-const LONG_UNBROKEN_TEXT = 'A'.repeat( 200 );
-// Shorter string for the custom opt-out height check (matches ciampo's reproduction).
-const OPT_OUT_UNBROKEN_TEXT = 'A'.repeat( 50 );
-
-async function expectNoHorizontalPageScroll( page ) {
-	await expect
-		.poll( async () => {
-			return page.evaluate( () => {
-				const root = document.documentElement;
-				return root.scrollWidth - root.clientWidth;
-			} );
-		} )
-		.toBeLessThanOrEqual( 1 );
-}
-
-// When the long string also appears in theme chrome (adjacent post nav, author
-// bio outside the block), page scrollWidth is not a reliable signal. Assert the
-// Media & Text block itself does not overflow its client box.
-async function expectMediaTextContentFits( page ) {
+const LONG_TEXT = 'A'.repeat( 200 );
+const LONG_LABEL = 'A'.repeat( 50 );
+const MEDIA_ATTRIBUTES = {
+	mediaType: 'image',
+	mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg',
+};
+
+async function expectContentToFit( block ) {
 	await expect
-		.poll( async () => {
-			return page.evaluate( () => {
-				const mediaText = document.querySelector(
-					'.wp-block-media-text'
-				);
-				return mediaText.scrollWidth - mediaText.clientWidth;
-			} );
-		} )
+		.poll( () =>
+			block.evaluate(
+				( element ) => element.scrollWidth - element.clientWidth
+			)
+		)
 		.toBeLessThanOrEqual( 1 );
 }
 
-async function expectNestedSearchButtonLabelSingleLine( page, buttonText ) {
-	const button = page.locator(
-		'.wp-block-media-text__content .wp-block-search__button'
-	);
-	await expect( button ).toBeVisible();
-	await expect( button ).toHaveCSS( 'overflow-wrap', 'normal' );
-
-	if ( buttonText.includes( '' ) || buttonText.includes( '' ) ) {
-		const formattedLabel = button.locator( 'strong, em' ).first();
-		await expect( formattedLabel ).toBeVisible();
-		await expect( formattedLabel ).toHaveCSS( 'overflow-wrap', 'normal' );
-	}
-
-	// Wrapped labels roughly double the button height (ciampo: ~31px → ~46px).
-	// line-height may be `normal` (e.g. emptytheme), so fall back to font-size.
+async function expectSingleLine( locator ) {
 	await expect
-		.poll( async () => {
-			return button.evaluate( ( el ) => {
-				const {
-					paddingTop,
-					paddingBottom,
-					borderTopWidth,
-					borderBottomWidth,
-					lineHeight,
-					fontSize,
-				} = window.getComputedStyle( el );
-				const verticalChrome =
-					parseFloat( paddingTop ) +
-					parseFloat( paddingBottom ) +
-					parseFloat( borderTopWidth ) +
-					parseFloat( borderBottomWidth );
-				const parsedLineHeight = parseFloat( lineHeight );
-				const resolvedLineHeight = Number.isFinite( parsedLineHeight )
-					? parsedLineHeight
-					: parseFloat( fontSize ) * 1.2;
-				const singleLineHeight = resolvedLineHeight + verticalChrome;
-				return el.getBoundingClientRect().height / singleLineHeight;
-			} );
-		} )
-		.toBeLessThan( 1.35 );
+		.poll( () =>
+			locator.evaluate( ( element ) => {
+				const range = document.createRange();
+				range.selectNodeContents( element );
+				return new Set(
+					[ ...range.getClientRects() ].map( ( rect ) =>
+						Math.round( rect.top )
+					)
+				).size;
+			} )
+		)
+		.toBe( 1 );
 }
 
-test.describe( 'Media & Text', () => {
-	// emptytheme has no `.entry-content p { overflow-wrap: break-word }`, so a
-	// custom `.no-break { overflow-wrap: normal }` opt-out can reach nested
-	// paragraphs via inheritance — matching ciampo's reproduction.
-	test.beforeAll( async ( { requestUtils } ) => {
-		await requestUtils.activateTheme( 'emptytheme' );
-	} );
-
+test.describe( 'Media & Text wrapping @webkit', () => {
 	test.beforeEach( async ( { admin } ) => {
 		await admin.createNewPost();
 	} );
 
-	test.afterAll( async ( { requestUtils } ) => {
-		await requestUtils.activateTheme( 'twentytwentyone' );
-	} );
-
-	for ( const { description, buttonText } of [
+	for ( const { description, innerBlock } of [
 		{
-			description: 'plain',
-			buttonText: LONG_BUTTON_LABEL,
+			description: 'a Paragraph with theme wrapping',
+			innerBlock: {
+				name: 'core/paragraph',
+				attributes: { content: LONG_TEXT },
+			},
 		},
 		{
-			description: 'bold',
-			buttonText: `${ LONG_BUTTON_LABEL }`,
+			description: 'a nested Quote',
+			innerBlock: {
+				name: 'core/quote',
+				innerBlocks: [
+					{
+						name: 'core/paragraph',
+						attributes: { content: LONG_TEXT },
+					},
+				],
+			},
+		},
+		{
+			description: 'a nested Code block',
+			innerBlock: {
+				name: 'core/code',
+				attributes: { content: LONG_TEXT },
+			},
 		},
 	] ) {
-		// eslint-disable-next-line playwright/expect-expect -- Asserted in the shared helper.
-		test( `should keep a nested Search button with a long custom ${ description } label on one line`, async ( {
+		test( `should keep long text in ${ description } within the content column`, async ( {
 			editor,
 			page,
 		} ) => {
 			await editor.insertBlock( {
 				name: 'core/media-text',
-				attributes: {
-					mediaType: 'image',
-					mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg',
-				},
-				innerBlocks: [
-					{
-						name: 'core/search',
-						attributes: {
-							label: 'Search',
-							showLabel: false,
-							buttonUseIcon: false,
-							buttonPosition: 'button-outside',
-							buttonText,
-						},
-					},
-				],
+				attributes: MEDIA_ATTRIBUTES,
+				innerBlocks: [ innerBlock ],
 			} );
 
+			const editorBlock = editor.canvas.locator( '.wp-block-media-text' );
+			await expect( editorBlock ).toContainText( LONG_TEXT );
+			await expectContentToFit( editorBlock );
+
 			const postId = await editor.publishPost();
 			await page.goto( `/?p=${ postId }` );
-
-			// Assertions live in the helper (overflow-wrap + single-line height).
-			await expectNestedSearchButtonLabelSingleLine( page, buttonText );
+			const block = page.locator( '.wp-block-media-text' );
+			await expect( block ).toContainText( LONG_TEXT );
+			await expectContentToFit( block );
 		} );
 	}
 
-	const nestedWrappingCases = [
-		{
-			name: 'Quote',
-			selector: '.wp-block-media-text__content .wp-block-quote',
-			innerBlocks: [
-				{
-					name: 'core/quote',
-					innerBlocks: [
-						{
-							name: 'core/paragraph',
-							attributes: { content: LONG_UNBROKEN_TEXT },
-						},
-					],
-				},
-			],
-		},
-		{
-			name: 'Pullquote',
-			selector: '.wp-block-media-text__content .wp-block-pullquote',
-			innerBlocks: [
-				{
-					name: 'core/pullquote',
-					attributes: { value: LONG_UNBROKEN_TEXT },
-				},
-			],
-		},
-		{
-			name: 'Code',
-			selector: '.wp-block-media-text__content .wp-block-code',
-			innerBlocks: [
-				{
-					name: 'core/code',
-					attributes: { content: LONG_UNBROKEN_TEXT },
-				},
-			],
-		},
-		{
-			name: 'Embed caption',
-			selector: '.wp-block-media-text__content .wp-block-embed',
-			innerBlocks: [
-				{
-					name: 'core/embed',
-					attributes: {
-						url: 'https://wordpress.org/gutenberg',
-						caption: LONG_UNBROKEN_TEXT,
-					},
-				},
-			],
-		},
-		{
-			name: 'Verse',
-			selector: '.wp-block-media-text__content .wp-block-verse',
-			innerBlocks: [
-				{
-					name: 'core/verse',
-					attributes: { content: LONG_UNBROKEN_TEXT },
-				},
-			],
-		},
-		{
-			name: 'Column',
-			selector: '.wp-block-media-text__content .wp-block-column',
+	test( 'should keep a formatted Search label inside a Column on one line', async ( {
+		editor,
+		page,
+	} ) => {
+		await editor.insertBlock( {
+			name: 'core/media-text',
+			attributes: MEDIA_ATTRIBUTES,
 			innerBlocks: [
 				{
 					name: 'core/columns',
@@ -205,9 +103,10 @@ test.describe( 'Media & Text', () => {
 							name: 'core/column',
 							innerBlocks: [
 								{
-									name: 'core/paragraph',
+									name: 'core/search',
 									attributes: {
-										content: LONG_UNBROKEN_TEXT,
+										showLabel: false,
+										buttonText: `${ LONG_LABEL }`,
 									},
 								},
 							],
@@ -215,214 +114,66 @@ test.describe( 'Media & Text', () => {
 					],
 				},
 			],
-		},
-	];
-
-	for ( const wrappingCase of nestedWrappingCases ) {
-		test( `should keep nested ${ wrappingCase.name } wrapping so the page does not scroll horizontally`, async ( {
-			editor,
-			page,
-		} ) => {
-			await editor.insertBlock( {
-				name: 'core/media-text',
-				attributes: {
-					mediaType: 'image',
-					mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg',
-				},
-				innerBlocks: wrappingCase.innerBlocks,
-			} );
-
-			const postId = await editor.publishPost();
-			await page.goto( `/?p=${ postId }` );
-
-			const nested = page.locator( wrappingCase.selector );
-			await expect( nested.first() ).toBeVisible();
-			await expect( nested.first() ).toHaveCSS(
-				'overflow-wrap',
-				'anywhere'
-			);
-			await expectNoHorizontalPageScroll( page );
 		} );
-	}
 
-	test( 'should keep nested Latest Posts titles wrapping so the page does not scroll horizontally', async ( {
+		const postId = await editor.publishPost();
+		await page.goto( `/?p=${ postId }` );
+		const button = page
+			.locator( '.wp-block-media-text' )
+			.getByRole( 'button', { name: LONG_LABEL } );
+		await expect( button ).toBeVisible();
+		await expectSingleLine( button.locator( 'strong' ) );
+	} );
+
+	test( 'should preserve a custom wrapping opt-out inside a Column', async ( {
 		editor,
 		page,
 		requestUtils,
 	} ) => {
-		const category = await requestUtils.rest( {
-			method: 'POST',
-			path: '/wp/v2/categories',
-			data: {
-				name: `Media Text Overflow ${ Date.now() }`,
-			},
-		} );
-
-		const fixturePost = await requestUtils.rest( {
-			method: 'POST',
-			path: '/wp/v2/posts',
-			data: {
-				title: LONG_UNBROKEN_TEXT,
-				status: 'publish',
-				categories: [ category.id ],
-				content: 'Latest Posts overflow-wrap fixture.',
-			},
-		} );
-
+		await requestUtils.activateTheme( 'emptytheme' );
 		try {
 			await editor.insertBlock( {
 				name: 'core/media-text',
-				attributes: {
-					mediaType: 'image',
-					mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg',
-				},
+				attributes: MEDIA_ATTRIBUTES,
 				innerBlocks: [
 					{
-						name: 'core/latest-posts',
-						attributes: {
-							postsToShow: 1,
-							displayPostContent: false,
-							categories: [ { id: category.id } ],
-						},
+						name: 'core/columns',
+						innerBlocks: [
+							{
+								name: 'core/column',
+								innerBlocks: [
+									{
+										name: 'core/group',
+										attributes: { className: 'no-break' },
+										innerBlocks: [
+											{
+												name: 'core/paragraph',
+												attributes: {
+													content: LONG_LABEL,
+												},
+											},
+										],
+									},
+								],
+							},
+						],
 					},
 				],
 			} );
 
 			const postId = await editor.publishPost();
 			await page.goto( `/?p=${ postId }` );
-
-			const latestPostsItem = page.locator(
-				'.wp-block-media-text__content .wp-block-latest-posts li'
-			);
-			await expect( latestPostsItem ).toHaveCount( 1 );
-			await expect( latestPostsItem ).toContainText( LONG_UNBROKEN_TEXT );
-			await expect( latestPostsItem ).toHaveCSS(
-				'overflow-wrap',
-				'anywhere'
-			);
-			// Long titles can also appear in theme post navigation outside the
-			// block, so assert on Media & Text not overflowing its client box.
-			await expectMediaTextContentFits( page );
-		} finally {
-			await requestUtils.rest( {
-				method: 'DELETE',
-				path: `/wp/v2/posts/${ fixturePost.id }`,
-				params: { force: true },
-			} );
-			await requestUtils.rest( {
-				method: 'DELETE',
-				path: `/wp/v2/categories/${ category.id }`,
-				params: { force: true },
-			} );
-		}
-	} );
-
-	test( 'should keep nested Author Biography wrapping so the page does not scroll horizontally', async ( {
-		editor,
-		page,
-		requestUtils,
-	} ) => {
-		const me = await requestUtils.rest( {
-			method: 'GET',
-			path: '/wp/v2/users/me',
-			params: { context: 'edit' },
-		} );
-		const previousDescription = me.description ?? '';
-
-		await requestUtils.rest( {
-			method: 'POST',
-			path: '/wp/v2/users/me',
-			data: { description: LONG_UNBROKEN_TEXT },
-		} );
-
-		try {
-			await editor.insertBlock( {
-				name: 'core/media-text',
-				attributes: {
-					mediaType: 'image',
-					mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg',
-				},
-				innerBlocks: [ { name: 'core/post-author-biography' } ],
+			await page.addStyleTag( {
+				content:
+					'.no-break { width: 220px; word-break: normal; overflow-wrap: normal; font: 16px/24px Arial; }',
 			} );
-
-			const postId = await editor.publishPost();
-			await page.goto( `/?p=${ postId }` );
-
-			const biography = page.locator(
-				'.wp-block-media-text__content .wp-block-post-author-biography'
+			const paragraph = page.locator(
+				'.wp-block-media-text .no-break p'
 			);
-			await expect( biography ).toBeVisible();
-			await expect( biography ).toHaveCSS( 'overflow-wrap', 'anywhere' );
-			// The same bio can render in theme chrome outside Media & Text, so
-			// assert on the block not overflowing its client box.
-			await expectMediaTextContentFits( page );
+			await expect( paragraph ).toHaveText( LONG_LABEL );
+			await expectSingleLine( paragraph );
 		} finally {
-			await requestUtils.rest( {
-				method: 'POST',
-				path: '/wp/v2/users/me',
-				data: { description: previousDescription },
-			} );
+			await requestUtils.activateTheme( 'twentytwentyone' );
 		}
 	} );
-
-	test( 'should preserve a nested custom overflow-wrap: normal opt-out', async ( {
-		editor,
-		page,
-	} ) => {
-		await editor.insertBlock( {
-			name: 'core/media-text',
-			attributes: {
-				mediaType: 'image',
-				mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg',
-			},
-			innerBlocks: [
-				{
-					name: 'core/group',
-					attributes: {
-						className: 'no-break',
-					},
-					innerBlocks: [
-						{
-							name: 'core/paragraph',
-							attributes: { content: OPT_OUT_UNBROKEN_TEXT },
-						},
-					],
-				},
-			],
-		} );
-
-		const postId = await editor.publishPost();
-		await page.goto( `/?p=${ postId }` );
-
-		await page.addStyleTag( {
-			content: `
-				.no-break {
-					width: 220px;
-					word-break: normal;
-					overflow-wrap: normal;
-					font-family: Arial, sans-serif;
-					font-size: 16px;
-					line-height: 24px;
-				}
-			`,
-		} );
-
-		const optOut = page.locator(
-			'.wp-block-media-text__content .no-break'
-		);
-		await expect( optOut ).toBeVisible();
-		await expect( optOut ).toHaveCSS( 'overflow-wrap', 'normal' );
-
-		const paragraph = optOut.locator( 'p' ).first();
-		await expect( paragraph ).toHaveCSS( 'overflow-wrap', 'normal' );
-		// With overflow-wrap: normal the 50 A's stay on one line (~24px).
-		// anywhere would wrap them to multiple lines (~72px at 220px width).
-		await expect
-			.poll( async () => {
-				return paragraph.evaluate(
-					( el ) => el.getBoundingClientRect().height
-				);
-			} )
-			.toBeLessThanOrEqual( 30 );
-	} );
 } );

From 0a1260adc66a044dac147f84c2bebc25f319c0cd Mon Sep 17 00:00:00 2001
From: Marco Ciampini 
Date: Mon, 12 Oct 2026 11:47:55 +0200
Subject: [PATCH 10/12] Media & Text: Remove takeover regression tests

---
 .../specs/editor/blocks/media-text.spec.js    | 179 ------------------
 1 file changed, 179 deletions(-)
 delete mode 100644 test/e2e/specs/editor/blocks/media-text.spec.js

diff --git a/test/e2e/specs/editor/blocks/media-text.spec.js b/test/e2e/specs/editor/blocks/media-text.spec.js
deleted file mode 100644
index aa6d699b2ec4f7..00000000000000
--- a/test/e2e/specs/editor/blocks/media-text.spec.js
+++ /dev/null
@@ -1,179 +0,0 @@
-const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' );
-
-const LONG_TEXT = 'A'.repeat( 200 );
-const LONG_LABEL = 'A'.repeat( 50 );
-const MEDIA_ATTRIBUTES = {
-	mediaType: 'image',
-	mediaUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg',
-};
-
-async function expectContentToFit( block ) {
-	await expect
-		.poll( () =>
-			block.evaluate(
-				( element ) => element.scrollWidth - element.clientWidth
-			)
-		)
-		.toBeLessThanOrEqual( 1 );
-}
-
-async function expectSingleLine( locator ) {
-	await expect
-		.poll( () =>
-			locator.evaluate( ( element ) => {
-				const range = document.createRange();
-				range.selectNodeContents( element );
-				return new Set(
-					[ ...range.getClientRects() ].map( ( rect ) =>
-						Math.round( rect.top )
-					)
-				).size;
-			} )
-		)
-		.toBe( 1 );
-}
-
-test.describe( 'Media & Text wrapping @webkit', () => {
-	test.beforeEach( async ( { admin } ) => {
-		await admin.createNewPost();
-	} );
-
-	for ( const { description, innerBlock } of [
-		{
-			description: 'a Paragraph with theme wrapping',
-			innerBlock: {
-				name: 'core/paragraph',
-				attributes: { content: LONG_TEXT },
-			},
-		},
-		{
-			description: 'a nested Quote',
-			innerBlock: {
-				name: 'core/quote',
-				innerBlocks: [
-					{
-						name: 'core/paragraph',
-						attributes: { content: LONG_TEXT },
-					},
-				],
-			},
-		},
-		{
-			description: 'a nested Code block',
-			innerBlock: {
-				name: 'core/code',
-				attributes: { content: LONG_TEXT },
-			},
-		},
-	] ) {
-		test( `should keep long text in ${ description } within the content column`, async ( {
-			editor,
-			page,
-		} ) => {
-			await editor.insertBlock( {
-				name: 'core/media-text',
-				attributes: MEDIA_ATTRIBUTES,
-				innerBlocks: [ innerBlock ],
-			} );
-
-			const editorBlock = editor.canvas.locator( '.wp-block-media-text' );
-			await expect( editorBlock ).toContainText( LONG_TEXT );
-			await expectContentToFit( editorBlock );
-
-			const postId = await editor.publishPost();
-			await page.goto( `/?p=${ postId }` );
-			const block = page.locator( '.wp-block-media-text' );
-			await expect( block ).toContainText( LONG_TEXT );
-			await expectContentToFit( block );
-		} );
-	}
-
-	test( 'should keep a formatted Search label inside a Column on one line', async ( {
-		editor,
-		page,
-	} ) => {
-		await editor.insertBlock( {
-			name: 'core/media-text',
-			attributes: MEDIA_ATTRIBUTES,
-			innerBlocks: [
-				{
-					name: 'core/columns',
-					innerBlocks: [
-						{
-							name: 'core/column',
-							innerBlocks: [
-								{
-									name: 'core/search',
-									attributes: {
-										showLabel: false,
-										buttonText: `${ LONG_LABEL }`,
-									},
-								},
-							],
-						},
-					],
-				},
-			],
-		} );
-
-		const postId = await editor.publishPost();
-		await page.goto( `/?p=${ postId }` );
-		const button = page
-			.locator( '.wp-block-media-text' )
-			.getByRole( 'button', { name: LONG_LABEL } );
-		await expect( button ).toBeVisible();
-		await expectSingleLine( button.locator( 'strong' ) );
-	} );
-
-	test( 'should preserve a custom wrapping opt-out inside a Column', async ( {
-		editor,
-		page,
-		requestUtils,
-	} ) => {
-		await requestUtils.activateTheme( 'emptytheme' );
-		try {
-			await editor.insertBlock( {
-				name: 'core/media-text',
-				attributes: MEDIA_ATTRIBUTES,
-				innerBlocks: [
-					{
-						name: 'core/columns',
-						innerBlocks: [
-							{
-								name: 'core/column',
-								innerBlocks: [
-									{
-										name: 'core/group',
-										attributes: { className: 'no-break' },
-										innerBlocks: [
-											{
-												name: 'core/paragraph',
-												attributes: {
-													content: LONG_LABEL,
-												},
-											},
-										],
-									},
-								],
-							},
-						],
-					},
-				],
-			} );
-
-			const postId = await editor.publishPost();
-			await page.goto( `/?p=${ postId }` );
-			await page.addStyleTag( {
-				content:
-					'.no-break { width: 220px; word-break: normal; overflow-wrap: normal; font: 16px/24px Arial; }',
-			} );
-			const paragraph = page.locator(
-				'.wp-block-media-text .no-break p'
-			);
-			await expect( paragraph ).toHaveText( LONG_LABEL );
-			await expectSingleLine( paragraph );
-		} finally {
-			await requestUtils.activateTheme( 'twentytwentyone' );
-		}
-	} );
-} );

From 8f5687e8fa2b68164bee583acd2fd650b8fb4f4e Mon Sep 17 00:00:00 2001
From: Marco Ciampini 
Date: Mon, 12 Oct 2026 12:01:59 +0200
Subject: [PATCH 11/12] Search: Scope wrapping reset to Media & Text

---
 packages/block-library/src/search/style.scss | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/packages/block-library/src/search/style.scss b/packages/block-library/src/search/style.scss
index 2e16a5a085b2f5..46b4638c0eee11 100644
--- a/packages/block-library/src/search/style.scss
+++ b/packages/block-library/src/search/style.scss
@@ -7,9 +7,12 @@ $button-spacing-y: math.div($grid-unit-15, 2); // 6px
 
 .wp-block-search__button {
 	margin-left: $button-spacing-x;
-	// Preserve the opt-out when an ancestor sets overflow-wrap.
 	word-break: normal;
-	overflow-wrap: normal;
+
+	.wp-block-media-text__content & {
+		// Preserve Search's opt-out inside Media & Text.
+		overflow-wrap: normal;
+	}
 
 	&.has-icon {
 		line-height: 0;

From 50fe030d9f716be3a755c08e5d3db7eaf6283a40 Mon Sep 17 00:00:00 2001
From: Marco Ciampini 
Date: Mon, 12 Oct 2026 17:56:37 +0200
Subject: [PATCH 12/12] Media & Text: Let nested Search labels inherit wrapping

---
 packages/block-library/CHANGELOG.md          | 2 +-
 packages/block-library/src/search/style.scss | 5 -----
 2 files changed, 1 insertion(+), 6 deletions(-)

diff --git a/packages/block-library/CHANGELOG.md b/packages/block-library/CHANGELOG.md
index 611ed06191ad8d..7c8f2918c24b5b 100644
--- a/packages/block-library/CHANGELOG.md
+++ b/packages/block-library/CHANGELOG.md
@@ -13,7 +13,7 @@
 
 ### Bug Fixes
 
--   Media & Text: Replace deprecated `word-break: break-word` while keeping long content within the text column and preserving nested wrapping opt-outs ([#82580](https://github.com/WordPress/gutenberg/pull/82580)).
+-   Media & Text: Replace deprecated `word-break: break-word` and prevent long content from widening the text column. Nested blocks that only override `word-break` can now wrap long unbroken text mid-word ([#82580](https://github.com/WordPress/gutenberg/pull/82580)).
 -   Accordion Heading: Anchor notes to the selected title text instead of the whole block ([#84497](https://github.com/WordPress/gutenberg/pull/84497)).
 
 ## 11.2.0 (2026-10-07)
diff --git a/packages/block-library/src/search/style.scss b/packages/block-library/src/search/style.scss
index 46b4638c0eee11..a39a5ceb335624 100644
--- a/packages/block-library/src/search/style.scss
+++ b/packages/block-library/src/search/style.scss
@@ -9,11 +9,6 @@ $button-spacing-y: math.div($grid-unit-15, 2); // 6px
 	margin-left: $button-spacing-x;
 	word-break: normal;
 
-	.wp-block-media-text__content & {
-		// Preserve Search's opt-out inside Media & Text.
-		overflow-wrap: normal;
-	}
-
 	&.has-icon {
 		line-height: 0;
 	}