diff --git a/php-transformer/src/HtmlToBlocks/Patterns/MediaTextPattern.php b/php-transformer/src/HtmlToBlocks/Patterns/MediaTextPattern.php
index 508b6fe7c..2f3b7a080 100644
--- a/php-transformer/src/HtmlToBlocks/Patterns/MediaTextPattern.php
+++ b/php-transformer/src/HtmlToBlocks/Patterns/MediaTextPattern.php
@@ -208,6 +208,23 @@ public function match(
return null;
}
+ // Out-of-flow media (`position: absolute`/`fixed`) sizes against its
+ // containing block — typically the source media wrapper that sets
+ // `position: relative`, a min-height and overflow clipping — not a grid
+ // track. core/media-text replaces that wrapper with its own figure, so
+ // the media would resolve against a distant ancestor (often the
+ // viewport) and cover the text pane. Keep the authored wrapper through
+ // ordinary flow lowering, mirroring the out-of-flow text-pane gate.
+ if ( $this->declaresUnresolvableGateValue($mediaStyle, array( 'position' )) ) {
+ return null;
+ }
+ $mediaPosition = strtolower($this->normalizedCssValue(
+ (string) ($this->styleDeclarations($mediaStyle)['position'] ?? '')
+ ));
+ if ( in_array($mediaPosition, array( 'absolute', 'fixed' ), true) ) {
+ return null;
+ }
+
// core/media-text sizes its panes as grid tracks: a percentage media
// track and the remainder for text. A flex row whose text pane alone
// grows into the free space beside a fixed-size media pane has no
diff --git a/php-transformer/tests/unit/media-text-pattern.php b/php-transformer/tests/unit/media-text-pattern.php
index 3bc8d0b11..a9b68bd6b 100644
--- a/php-transformer/tests/unit/media-text-pattern.php
+++ b/php-transformer/tests/unit/media-text-pattern.php
@@ -1488,6 +1488,20 @@ static function (string $name, array $attrs, array $innerBlocks, ?DOMElement $so
$assertTrue(is_array($genuineTwoPaneBlock), 'A genuine in-flow media/text pair still converts to core/media-text.');
$assertSame('core/heading', $genuineTwoPaneBlock['innerBlocks'][0]['blockName'] ?? null, 'Genuine two-pane text side keeps its heading identity.');
+// Out-of-flow media sizes against its source wrapper (the containing block),
+// not a media-text grid track. Replacing that wrapper with media-text's figure
+// lets the image resolve against the viewport, so the pattern declines and the
+// authored wrapper survives with its stylesheet positioning.
+$positionedMediaHtml = ''
+ . '
Heading
Copy beside a cover image.
'
+ . '
';
+$positionedMediaResult = $transformHtml($positionedMediaHtml);
+$assertNull($collectMediaText($positionedMediaResult['blocks'] ?? array()), 'Absolutely positioned media keeps its source wrapper instead of lowering to core/media-text.');
+$fixedMediaResult = $transformHtml(str_replace('position:absolute}', 'position:fixed}', $positionedMediaHtml));
+$assertNull($collectMediaText($fixedMediaResult['blocks'] ?? array()), 'Fixed-position media also declines core/media-text.');
+$inFlowMediaResult = $transformHtml(str_replace(';position:absolute}', '}', $positionedMediaHtml));
+$assertTrue(is_array($collectMediaText($inFlowMediaResult['blocks'] ?? array())), 'In-flow media in the same layout still lowers to core/media-text.');
+
if ( 0 === $failures ) {
echo "media text pattern ok\n";
}